]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_transformations/ast2pres.ml
0eba3757fcb5b016846151d19b63ec9742177878
[helm.git] / helm / ocaml / cic_transformations / ast2pres.ml
1 (* Copyright (C) 2000, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (**************************************************************************)
27 (*                                                                        *)
28 (*                           PROJECT HELM                                 *)
29 (*                                                                        *)
30 (*                Andrea Asperti <asperti@cs.unibo.it>                    *)
31 (*                             28/6/2003                                  *)
32 (*                                                                        *)
33 (**************************************************************************)
34
35 module A = CicAst;;
36 module P = Mpresentation;;
37
38 let symbol_table = Hashtbl.create 503;;
39 let symbol_table_charcount = Hashtbl.create 503;;
40
41 let maxsize = 25;;
42
43 let rec countvar current_size = function
44     (Cic.Anonymous, None) -> current_size + 1 (* underscore *)
45   | (Cic.Anonymous, Some ty) -> countterm current_size ty
46   | (Cic.Name s, None) -> current_size + String.length s
47   | (Cic.Name s, Some ty) -> current_size + countterm current_size ty
48
49 and countterm current_size t =
50   if current_size > maxsize then current_size 
51   else match t with
52       A.AttributedTerm (_,t) -> countterm current_size t
53     | A.Appl l -> 
54         List.fold_left countterm current_size l
55     | A.Binder (_,var,body) -> 
56         let varsize = countvar current_size var in
57         countterm (varsize + 1) body (* binder *)
58     | A.Case (arg, _, ty, pl) ->
59         let size1 = countterm (current_size+10) arg in (* match with *)
60         let size2 =
61           match ty with
62               None -> size1
63             | Some ty -> countterm size1 ty in
64         List.fold_left 
65           (fun c ((constr,vars),action) ->
66              let size3 =
67                List.fold_left countvar (c+String.length constr) vars in
68              countterm size3 action) size2 pl 
69     | A.LetIn (var,s,t) ->
70         let size1 = countvar current_size var in
71         let size2 = countterm size1 s in
72         countterm size2 t
73     | A.LetRec (_,l,t) ->
74         let size1 =
75           List.fold_left
76             (fun c (var,s,_) -> 
77                let size1 = countvar c var in
78                countterm size1 s) current_size l in
79           countterm size1 t
80     | A.Ident (s,None)
81     | A.Uri (s, None) -> current_size + (String.length s)
82     | A.Ident (s,Some l)
83     | A.Uri (s,Some l) ->
84         List.fold_left 
85           (fun c (v,t) -> countterm (c + (String.length v)) t) 
86           (current_size + (String.length s)) l
87     | A.Implicit -> current_size + 1 (* underscore *)
88     | A.Meta (_,l) ->
89         List.fold_left 
90           (fun c t -> 
91              match t with
92                  None -> c + 1 (* underscore *)
93                | Some t -> countterm c t)
94           (current_size + 1) l (* num *)
95     | A.Num (s, _) -> current_size + String.length s
96     | A.Sort _ -> current_size + 4 (* sort name *)
97     | A.Symbol (s,_) -> current_size + String.length s
98
99     | A.UserInput -> current_size
100 ;;
101
102 let is_big t = 
103   ((countterm 0 t) > maxsize)
104 ;;
105
106 let rec make_attributes l1 =
107   function
108       [] -> []
109     | None::tl -> make_attributes (List.tl l1) tl
110     | (Some s)::tl ->
111        let p,n = List.hd l1 in
112         (p,n,s)::(make_attributes (List.tl l1) tl)
113 ;;
114
115 let map_tex unicode texcmd =
116   let default_map_tex = Printf.sprintf "\\%s " in
117   if unicode then
118     try
119       Utf8Macro.expand texcmd
120     with Utf8Macro.Macro_not_found _ -> default_map_tex texcmd
121   else
122     default_map_tex texcmd
123
124 let resolve_binder unicode = function
125   | `Lambda -> map_tex unicode "lambda"
126   | `Pi -> map_tex unicode "Pi"
127   | `Forall -> map_tex unicode "forall"
128   | `Exists -> map_tex unicode "exists"
129 ;;
130
131 let rec make_args f ~tail = function
132     | [] -> assert false
133     | [arg] -> [f ~tail arg]
134     | arg :: tl -> (f ~tail:[] arg) :: (make_args f ~tail tl)
135
136 let append_tail ~tail box =
137   match tail with
138   | [] -> box
139   | _ -> Box.H ([], box :: (List.map (fun t -> Box.Text ([], t)) tail))
140
141 let ast2astBox ?(unicode = true) ?(priority = 0) ?(assoc = false) ?(tail = [])
142   (t, ids_to_uris)
143 =
144   let lookup_uri = function
145     | None -> None
146     | Some id ->
147         (try
148           Some (Hashtbl.find ids_to_uris id)
149         with Not_found -> None)
150   in
151   let make_std_attributes xref =
152     let uri = lookup_uri xref in
153     make_attributes [Some "helm","xref"; Some "xlink","href"] [xref;uri]
154   in
155   let rec ast2box ?(priority = 0) ?(assoc = false) ?xref ~tail t =
156     if is_big t then 
157       bigast2box ~priority ~assoc ?xref ~tail t
158     else
159       let attrs = make_std_attributes xref in
160       append_tail ~tail (Box.Object (attrs, t))
161   and
162   bigast2box ?(priority = 0) ?(assoc = false) ?xref ~tail t =
163   match t with
164     | A.AttributedTerm (`Loc _, t) -> bigast2box ?xref ~tail t
165     | A.AttributedTerm (`IdRef xref, t) -> bigast2box ~xref ~tail t
166     | A.Appl [] -> assert false
167     | A.Appl ((hd::tl) as l) ->
168         let rec find_symbol idref = function
169           | A.AttributedTerm (`Loc _, t) -> find_symbol None t
170           | A.AttributedTerm (`IdRef id, t) -> find_symbol (Some id) t
171           | A.Symbol (name, _) ->
172               (match idref with
173               | None -> assert false
174               | Some idref -> `Symbol (name, idref))
175           | _ -> `None
176         in
177         let aattr = make_attributes [Some "helm","xref"] [xref] in
178         (match find_symbol None hd with
179         | `Symbol (name, sxref) ->
180             let sattr = make_std_attributes (Some sxref) in
181             (try 
182               (let f = Hashtbl.find symbol_table_charcount name in
183                f tl ~unicode ~priority ~assoc ~tail ~ids_to_uris aattr sattr)
184             with Not_found ->
185               Box.H 
186                 (make_attributes [Some "helm","xref"] [xref],
187                  [Box.Text([],"(");
188                   Box.V([],
189                     make_args (fun ~tail t -> ast2box ~tail t)
190                       ~tail:(")" :: tail) l);
191                   Box.Text([],")")]))
192         | `None ->
193             Box.H 
194               (make_attributes [Some "helm","xref"] [xref],
195                [Box.Text([],"(");
196                 Box.V([],
197                   make_args
198                     (fun ~tail t -> ast2box ~tail t)
199                     ~tail:(")" :: tail) l)]
200                 ))
201     | A.Binder (`Forall, (Cic.Anonymous, typ), body)
202     | A.Binder (`Pi, (Cic.Anonymous, typ), body) ->
203         Box.V(make_attributes [Some "helm","xref"] [xref],
204           [(match typ with
205             | None -> Box.Text([], "?")
206             | Some typ -> ast2box ~tail:[] typ);
207             Box.H([],
208               [Box.skip;
209                Box.Text([], map_tex unicode "to");
210                ast2box ~tail body])])
211     | A.Binder(kind, var, body) ->
212         Box.V(make_attributes [Some "helm","xref"] [xref],
213               [Box.H([],
214                 [Box.Text ([None,"color","blue"], resolve_binder unicode kind);
215                  make_var ~tail:("." :: tail) var]);
216                Box.indent (ast2box ~tail body)])
217     | A.Case(arg, _, ty, pl) ->
218         let make_rule ~tail sep ((constr,vars),rhs) =
219           if (is_big rhs) then
220             Box.V([],[Box.H([],[Box.Text([],sep);
221                                 Box.smallskip; 
222                                 make_pattern constr vars;
223                                 Box.smallskip; 
224                                 Box.Text([],map_tex unicode "Rightarrow")]);
225                       Box.indent (bigast2box ~tail rhs)])
226           else
227             Box.H([],[Box.Text([],sep);
228                       Box.smallskip; 
229                       make_pattern constr vars;
230                       Box.smallskip; 
231                       Box.Text([],map_tex unicode "Rightarrow");
232                       Box.smallskip; 
233                       Box.Object([],rhs)]) in
234         let plbox = match pl with
235             [] -> Box.Text([],"[]")
236           | r::tl -> 
237               Box.V([],
238                 (make_rule ~tail:[] "[" r) ::
239                 (make_args
240                   (fun ~tail pat -> make_rule ~tail:[] "|" pat)
241                   ~tail:("]" :: tail)
242                   tl))
243         in
244         let ty_box =
245           match ty with
246           | Some ty ->
247               [ Box.H([],[Box.Text([],"[");
248                          ast2box ~tail ty;
249                          Box.Text([],"]")]) ]
250           | None -> []
251         in
252         if is_big arg then
253           Box.V(make_attributes [Some "helm","xref"] [xref],
254                  ty_box @
255                  [Box.Text([],"match");
256                  Box.indent (Box.H([],[Box.skip; bigast2box ~tail arg]));
257                  Box.Text([],"with");
258                  Box.indent plbox])
259         else
260           Box.V(make_attributes [Some "helm","xref"] [xref],
261                 ty_box @
262                 [Box.H(make_attributes [Some "helm","xref"] [xref],
263                        [Box.Text([],"match");
264                         Box.smallskip;
265                         ast2box ~tail arg;
266                         Box.smallskip;
267                         Box.Text([],"with")]);
268                  Box.indent plbox])
269     | A.LetIn (var, s, t) ->
270         Box.V(make_attributes [Some "helm","xref"] [xref],
271               (make_def "let" var s "in")@[ast2box ~tail t])
272     | A.LetRec (_, vars, body) ->
273         let definitions =
274           let rec make_defs let_txt = function
275               [] -> []
276             | [(var,s,_)] -> 
277                 make_def let_txt var s "in"
278             | (var,s,_)::tl ->
279                 (make_def let_txt var s "")@(make_defs "and" tl) in
280           make_defs "let rec" vars in
281         Box.V(make_attributes [Some "helm","xref"] [xref],
282               definitions@[ast2box ~tail body])
283     | A.Ident (s, subst)
284     | A.Uri (s, subst) ->
285         let subst =
286           let rec make_substs start_txt = 
287             function
288               [] -> []
289             | [(s,t)] -> 
290                 make_subst start_txt s t ""
291             | (s,t)::tl ->
292                 (make_subst start_txt s t ";")@(make_substs "" tl)
293           in
294           match subst with
295           | Some subst ->
296               Box.H([],
297                     [Box.Text(make_std_attributes xref,s);
298                      Box.Action([],
299                        [Box.Text([],"[...]");
300                         Box.H([], [Box.Text([], map_tex unicode "subst" ^ "[");
301                          Box.V([], make_substs "" subst);
302                          Box.Text([], "]")])])])
303           | None -> Box.Text(make_std_attributes xref, s)
304         in
305          subst
306         (*
307         Box.H([], (* attr here or on Vbox? *)
308               [Box.Text(make_std_attributes xref,s);
309                Box.Action([], [Box.Text([], "[_]"); Box.V([],subst)])])
310                (* Box.indent(Box.V([],subst))]) *)
311         *)
312     | A.Implicit -> 
313         Box.Text([],"_") (* big? *)
314     | A.Meta (n, l) ->
315         let local_context =
316           List.map 
317             (function t -> 
318                Box.H([],[aux_option ~tail t; Box.Text([],";")])) 
319             l in
320         Box.V(make_attributes [Some "helm","xref"] [xref],
321               [Box.Text([],"?"^(string_of_int n));
322                Box.H([],[Box.Text([],"[");
323                          Box.V([],local_context);
324                          Box.Text([],"]")])])
325     | A.Num (s, _) -> 
326          Box.Text([],s)
327     | A.Sort kind ->
328         (match kind with 
329              `Prop -> Box.Text([],"Prop")
330            | `Set -> Box.Text([],"Set")
331            | `Type -> Box.Text([],"Type")   
332            | `CProp -> Box.Text([],"CProp"))    
333     | A.Symbol (s, _) -> 
334         Box.Text([],s)
335
336     | A.UserInput -> Box.Text([],"")
337
338   and aux_option ~tail = function
339       None  -> Box.Text([],"_")
340     | Some ast -> ast2box ~tail ast 
341
342   and make_var ~tail = function
343       (Cic.Anonymous, None) -> Box.Text([],"_:_")
344     | (Cic.Anonymous, Some t) -> 
345         Box.H([],[Box.Text([],"_:");ast2box ~tail t])
346     | (Cic.Name s, None) -> Box.Text([],s)
347     | (Cic.Name s, Some t) ->
348         if is_big t then
349           Box.V([],[Box.Text([],s^":");
350                     Box.indent(bigast2box ~tail t)])
351         else
352           Box.H([],[Box.Text([],s^":");Box.Object([],t)])
353
354   and make_pattern constr = 
355     function
356         [] -> Box.Text([],constr)
357       | vars -> 
358           let bvars =
359             List.fold_right 
360               (fun var acc -> 
361                  let bv = 
362                    match var with
363                        (* ignoring the type *)
364                        (Cic.Anonymous, _) -> Box.Text([],"_")
365                      | (Cic.Name s, _) -> Box.Text([],s) in
366                    Box.Text([]," ")::bv::acc) vars [Box.Text([],")")] in
367             Box.H([],Box.Text([],"(")::Box.Text([],constr)::bvars)
368       
369
370   and make_def let_txt var def end_txt =
371     let name = 
372       (match var with
373            (* ignoring the type *)
374            (Cic.Anonymous, _) -> Box.Text([],"_") 
375          | (Cic.Name s, _) -> Box.Text([],s)) in
376     pretty_append ~tail:[end_txt]
377       [Box.Text([],let_txt);
378        Box.smallskip;
379        name;
380        Box.smallskip;
381        Box.Text([],"=")
382       ]
383       def 
384
385   and make_subst start_txt varname body end_txt =
386     pretty_append ~tail:[end_txt]
387       ((if start_txt <> "" then [Box.Text([],start_txt)] else [])@
388        [Box.Text([],varname);
389         Box.smallskip;
390         Box.Text([],map_tex unicode "Assign")
391        ])
392       body
393             
394   and pretty_append ~tail l ast =
395     if is_big ast then
396       [Box.H([],l);
397        Box.H([],[Box.skip; bigast2box ~tail ast])]
398     else
399       [Box.H([],l@[Box.smallskip; (ast2box ~tail ast)])]
400
401 in
402 ast2box ~priority ~assoc ~tail t
403 ;;
404
405 let m_row_with_fences = P.row_with_brackets
406 let m_row = P.row_without_brackets
407 let m_open_fence = P.Mo([None, "stretchy", "false"], "(")
408 let m_close_fence = P.Mo([None, "stretchy", "false"], ")")
409
410 let ast2mpres ?(priority = 0) ?(assoc = false) (ast, ids_to_uris) =
411   let lookup_uri = function
412     | None -> None
413     | Some id ->
414         (try
415           Some (Hashtbl.find ids_to_uris id)
416         with Not_found -> None)
417   in
418   let make_std_attributes xref =
419     let uri = lookup_uri xref in
420     make_attributes [Some "helm","xref"; Some "xlink","href"] [xref;uri]
421   in
422   let rec aux ?xref =
423   function
424     | A.AttributedTerm (`Loc _, ast) -> aux ?xref ast
425     | A.AttributedTerm (`IdRef xref, ast) -> aux ~xref ast
426     | A.Symbol (name,_) -> 
427         let attr = make_std_attributes xref in
428         P.Mi (attr,name)
429     | A.Ident (name,subst)
430     | A.Uri (name,subst) ->
431         let attr = make_std_attributes xref in
432         let rec make_subst =
433           (function 
434               [] -> []
435             | (n,a)::tl ->
436                 (aux a)::
437                 P.Mtext([],"/")::
438                 P.Mi([],n)::
439                 P.Mtext([],"; ")::
440                 P.smallskip::
441                 (make_subst tl)) in
442         let subst =
443           match subst with
444           | None -> []
445           | Some subst -> make_subst subst
446         in
447         (match subst with
448         | [] -> P.Mi (attr, name)
449         | _ ->
450             P.Mrow ([],
451               P.Mi (attr,name)::
452               P.Mtext([],"[")::
453               subst @
454               [(P.Mtext([],"]"))]))
455     | A.Meta (no,l) ->
456         let attr = make_attributes [Some "helm","xref"] [xref] in
457         let l' =
458          List.map
459           (function
460               None -> P.Mo([],"_")
461             | Some t -> aux t
462           ) l
463         in
464          P.Mrow ([],P.Mi (attr,"?" ^ string_of_int no) :: P.Mo ([],"[") ::
465            l' @ [P.Mo ([],"]")])
466     | A.Num (value, _) -> 
467         let attr = make_attributes [Some "helm","xref"] [xref] in
468         P.Mn (attr,value)
469     | A.Sort `Prop -> P.Mtext ([], "Prop")
470     | A.Sort `Set -> P.Mtext ([], "Set")
471     | A.Sort `Type -> P.Mtext ([], "Type")
472     | A.Sort `CProp -> P.Mtext ([], "CProp")
473     | A.Implicit -> P.Mtext([], "?")
474     | A.UserInput -> P.Mtext([], "")
475     | A.Appl [] -> assert false
476     | A.Appl ((hd::tl) as l) ->
477         let rec find_symbol idref = function
478           | A.AttributedTerm (`Loc _, t) -> find_symbol None t
479           | A.AttributedTerm (`IdRef id, t) -> find_symbol (Some id) t
480           | A.Symbol (name, _) ->
481               (match idref with
482               | None -> assert false
483               | Some idref -> `Symbol (name, idref))
484           | term ->
485               `None
486         in
487         let aattr = make_attributes [Some "helm","xref"] [xref] in
488         (match find_symbol None hd with
489         | `Symbol (name, sxref) ->
490             let sattr = make_std_attributes (Some sxref) in
491             (try 
492               (let f = Hashtbl.find symbol_table name in
493                f tl ~priority ~assoc ~ids_to_uris aattr sattr)
494             with Not_found ->
495               P.Mrow(aattr,
496               m_open_fence :: P.Mi(sattr,name)::(make_args tl) @
497               [m_close_fence]))
498         | `None ->
499             P.Mrow(aattr, m_open_fence :: (aux hd) :: (make_args tl) @
500             [m_close_fence]))
501     | A.Binder (`Pi, (Cic.Anonymous, Some ty), body)
502     | A.Binder (`Forall, (Cic.Anonymous, Some ty), body) ->
503         let attr = make_attributes [Some "helm","xref"] [xref] in
504         P.Mrow (attr, [
505           aux ty;
506           P.Mtext ([], map_tex true "to");
507           aux body])
508     | A.Binder (kind,var,body) ->
509         let attr = make_attributes [Some "helm","xref"] [xref] in
510         let binder = resolve_binder true kind in
511         let var = make_capture_variable var in
512         P.Mrow (attr, 
513            P.Mtext([None,"mathcolor","blue"],binder) :: var @ 
514            [P.Mo([],"."); aux body])
515     | A.LetIn (var,s,body) ->
516         let attr = make_attributes [Some "helm","xref"] [xref] in
517         P.Mrow (attr, 
518            P.Mtext([],("let ")) ::
519            (make_capture_variable var @
520            P.Mtext([],("="))::
521            (aux s)::
522            P.Mtext([]," in ")::
523            [aux body]))
524     | A.LetRec (_, defs, body) ->
525         let attr = make_attributes [Some "helm","xref"] [xref] in
526         let rec make_defs =
527           (function 
528                [] -> assert false
529              | [(var,body,_)] -> 
530                  make_capture_variable var @ [P.Mtext([],"=");(aux body)]
531              | (var,body,_)::tl -> 
532                  make_capture_variable var @
533                  (P.Mtext([],"=")::
534                   (aux body)::P.Mtext([]," and")::(make_defs tl))) in
535         P.Mrow (attr,  
536           P.Mtext([],("let rec "))::
537           (make_defs defs)@
538            (P.Mtext([]," in ")::
539            [aux body]))
540     | A.Case (arg,_,outtype,patterns) ->
541         (* TODO print outtype *)
542         let attr = make_attributes [Some "helm","xref"] [xref] in
543         let rec make_patterns =
544           (function 
545                [] -> []
546              | [(constr, vars),rhs] -> make_pattern constr vars rhs
547              | ((constr,vars), rhs)::tl -> 
548                  (make_pattern constr vars rhs)@(P.smallskip::
549                  P.Mtext([],"|")::P.smallskip::(make_patterns tl)))
550         and make_pattern constr vars rhs =           
551           let lhs = 
552             P.Mtext([], constr) ::
553               (List.concat
554                 (List.map (fun var -> P.smallskip :: make_capture_variable var)
555                   vars))
556           in
557           lhs @
558           [P.smallskip; P.Mtext([],map_tex true "to"); P.smallskip; aux rhs]
559         in
560         P.Mrow (attr,
561           P.Mtext([],"match")::P.smallskip::
562           (aux arg)::P.smallskip::
563           P.Mtext([],"with")::P.smallskip::
564           P.Mtext([],"[")::P.smallskip::
565           (make_patterns patterns)@(P.smallskip::[P.Mtext([],("]"))]))
566
567   and make_capture_variable (name, ty) =
568     let name =
569       match name with
570       | Cic.Anonymous -> [P.Mtext([], "_")]
571       | Cic.Name s -> [P.Mtext([], s)]
572     in
573     let ty =
574       match ty with
575       | None -> []
576       | Some ty -> [P.Mtext([],":"); aux ty]
577     in
578     name @ ty
579
580   and make_args ?(priority = 0) ?(assoc = false) =
581     function
582         [] -> []
583       | a::tl -> P.smallskip::(aux a)::(make_args tl)
584
585   in
586   aux ast
587 ;;
588
589 let box_prefix = "b";;
590
591 let add_xml_declaration stream =
592   [<
593     Xml.xml_cdata "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ;
594     Xml.xml_cdata "\n";
595     Xml.xml_nempty ~prefix:box_prefix "box"
596       [ Some "xmlns","m","http://www.w3.org/1998/Math/MathML" ;
597         Some "xmlns","b","http://helm.cs.unibo.it/2003/BoxML" ;
598         Some "xmlns","helm","http://www.cs.unibo.it/helm" ;
599         Some "xmlns","xlink","http://www.w3.org/1999/xlink"
600       ] stream
601   >]
602
603 let ast2mpresXml ((ast, ids_to_uris) as arg) =
604   let astBox = ast2astBox arg in
605   let smallAst2mpresXml ast =
606     P.print_mpres (ast2mpres (ast, ids_to_uris))
607   in
608   (Box.box2xml ~obj2xml:smallAst2mpresXml astBox)
609
610 let b_open_fence = Box.b_text [] "("
611 let b_close_fence = Box.b_text [] ")"
612 let b_v_with_fences attrs a b op =
613   Box.b_h attrs [
614     b_open_fence;
615     Box.b_v [] [
616       a;
617       Box.b_h [] [ op; b ]
618     ];
619     b_close_fence
620   ]
621 let b_v_without_fences attrs a b op =
622   Box.b_v attrs [
623     a;
624     Box.b_h [] [ op; b ]
625   ]
626
627 let _ = (** fill symbol_table *)
628   let binary f = function [a;b] -> f a b | _ -> assert false in
629   let unary f = function [a] -> f a | _ -> assert false in
630   let add_binary_op name threshold ?(assoc=`Left) symbol =
631     let assoc = match assoc with `Left -> true | `Right -> false in
632     Hashtbl.add symbol_table name (binary
633       (fun a b ~priority ~assoc ~ids_to_uris aattr sattr ->
634         let symbol =
635           match symbol with
636           | `Symbol name -> map_tex true name
637           | `Ascii s -> s
638         in
639          if (priority > threshold) || (priority = threshold && assoc) then
640            m_row_with_fences aattr
641              (ast2mpres ~priority:threshold ~assoc (a, ids_to_uris))
642              (ast2mpres ~priority:threshold ~assoc:(not assoc) (b, ids_to_uris))
643              (P.Mo(sattr,symbol))
644          else 
645            m_row aattr
646              (ast2mpres ~priority:threshold ~assoc (a, ids_to_uris))
647              (ast2mpres ~priority:threshold ~assoc:(not assoc) (b, ids_to_uris))
648              (P.Mo(sattr,symbol))));
649     Hashtbl.add symbol_table_charcount name (binary
650       (fun a b ~unicode ~priority ~assoc ~tail ~ids_to_uris aattr sattr ->
651         let symbol =
652           match symbol with
653           | `Symbol name -> map_tex unicode name
654           | `Ascii s -> s
655         in
656
657          if (priority > threshold) || (priority = threshold && assoc) then
658            b_v_with_fences aattr
659              (ast2astBox ~priority:threshold ~assoc ~tail:[] (a, ids_to_uris))
660              (ast2astBox ~priority:threshold ~assoc:(not assoc) ~tail
661               (b, ids_to_uris))
662              (Box.Text(sattr,symbol))
663          else 
664            b_v_without_fences aattr
665              (ast2astBox ~priority:threshold ~assoc ~tail:[] (a, ids_to_uris))
666              (ast2astBox ~priority:threshold ~assoc:(not assoc) ~tail
667               (b, ids_to_uris))
668              (Box.Text(sattr,symbol))))
669   in
670   Hashtbl.add symbol_table "not" (unary
671     (fun a ~priority ~assoc ~ids_to_uris attr sattr ->
672        (P.Mrow([], [
673          m_open_fence; P.Mo([],map_tex true "lnot");
674          ast2mpres (a, ids_to_uris); m_close_fence]))));
675   Hashtbl.add symbol_table "inv" (unary
676     (fun a ~priority ~assoc ~ids_to_uris attr sattr ->
677       P.Msup([],
678         P.Mrow([],[ m_open_fence; ast2mpres (a, ids_to_uris); m_close_fence]),
679         P.Mrow([],[ P.Mo([],"-"); P.Mn([],"1")]))));
680   Hashtbl.add symbol_table "opp" (unary
681     (fun a ~priority ~assoc ~ids_to_uris attr sattr ->
682       P.Mrow([],[
683         P.Mo([],"-");
684         m_open_fence;
685         ast2mpres (a, ids_to_uris);
686         m_close_fence])));
687   add_binary_op "arrow" 5 ~assoc:`Right (`Symbol "to");
688   add_binary_op "eq" 40 (`Ascii "=");
689   add_binary_op "and" 20 (`Symbol "land");
690   add_binary_op "or" 10 (`Symbol "lor");
691   add_binary_op "iff" 5 (`Symbol "iff");
692   add_binary_op "leq" 40 (`Symbol "leq");
693   add_binary_op "lt" 40 (`Symbol "lt");
694   add_binary_op "geq" 40 (`Symbol "geq");
695   add_binary_op "gt" 40 (`Symbol "gt");
696   add_binary_op "plus" 60 (`Ascii "+");
697   add_binary_op "times" 70 (`Ascii "*");
698   add_binary_op "minus" 60 (`Ascii "-");
699   add_binary_op "div" 60 (`Ascii "/");
700