]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_transformations/ast2pres.ml
version 0.7.1
[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 rec find_symbol idref = function
142   | A.AttributedTerm (`Loc _, t) -> find_symbol None t
143   | A.AttributedTerm (`IdRef id, t) -> find_symbol (Some id) t
144   | A.Symbol (name, _) -> `Symbol (name, idref)
145   | _ -> `None
146
147 let ast2astBox ?(unicode = true) ?(priority = 0) ?(assoc = false) ?(tail = [])
148   (t, ids_to_uris)
149 =
150   let lookup_uri = function
151     | None -> None
152     | Some id ->
153         (try
154           Some (Hashtbl.find ids_to_uris id)
155         with Not_found -> None)
156   in
157   let make_std_attributes xref =
158     let uri = lookup_uri xref in
159     make_attributes [Some "helm","xref"; Some "xlink","href"] [xref;uri]
160   in
161   let rec ast2box ?(priority = 0) ?(assoc = false) ?xref ~tail t =
162     if is_big t then 
163       bigast2box ~priority ~assoc ?xref ~tail t
164     else
165       let attrs = make_std_attributes xref in
166       append_tail ~tail (Box.Object (attrs, t))
167   and
168   bigast2box ?(priority = 0) ?(assoc = false) ?xref ~tail t =
169   match t with
170     | A.AttributedTerm (`Loc _, t) -> bigast2box ?xref ~tail t
171     | A.AttributedTerm (`IdRef xref, t) -> bigast2box ~xref ~tail t
172     | A.Appl [] -> assert false
173     | A.Appl ((hd::tl) as l) ->
174         let aattr = make_attributes [Some "helm","xref"] [xref] in
175         (match find_symbol None hd with
176         | `Symbol (name, sxref) ->
177             let sattr = make_std_attributes sxref in
178             (try 
179               (let f = Hashtbl.find symbol_table_charcount name in
180                f tl ~unicode ~priority ~assoc ~tail ~ids_to_uris aattr sattr)
181             with Not_found ->
182               Box.H 
183                 (make_attributes [Some "helm","xref"] [xref],
184                  [Box.Text([],"(");
185                   Box.V([],
186                     make_args (fun ~tail t -> ast2box ~tail t)
187                       ~tail:(")" :: tail) l);
188                   Box.Text([],")")]))
189         | `None ->
190             Box.H 
191               (make_attributes [Some "helm","xref"] [xref],
192                [Box.Text([],"(");
193                 Box.V([],
194                   make_args
195                     (fun ~tail t -> ast2box ~tail t)
196                     ~tail:(")" :: tail) l)]
197                 ))
198     | A.Binder (`Forall, (Cic.Anonymous, typ), body)
199     | A.Binder (`Pi, (Cic.Anonymous, typ), body) ->
200         Box.V(make_attributes [Some "helm","xref"] [xref],
201           [(match typ with
202             | None -> Box.Text([], "?")
203             | Some typ -> ast2box ~tail:[] typ);
204             Box.H([],
205               [Box.skip;
206                Box.Text([], map_tex unicode "to");
207                ast2box ~tail body])])
208     | A.Binder(kind, var, body) ->
209         Box.V(make_attributes [Some "helm","xref"] [xref],
210               [Box.H([],
211                 [Box.Text ([None,"color","blue"], resolve_binder unicode kind);
212                  make_var ~tail:("." :: tail) var]);
213                Box.indent (ast2box ~tail body)])
214     | A.Case(arg, _, ty, pl) ->
215         let make_rule ~tail sep ((constr,vars),rhs) =
216           if (is_big rhs) then
217             Box.V([],[Box.H([],[Box.Text([],sep);
218                                 Box.smallskip; 
219                                 make_pattern constr vars;
220                                 Box.smallskip; 
221                                 Box.Text([],map_tex unicode "Rightarrow")]);
222                       Box.indent (bigast2box ~tail rhs)])
223           else
224             Box.H([],[Box.Text([],sep);
225                       Box.smallskip; 
226                       make_pattern constr vars;
227                       Box.smallskip; 
228                       Box.Text([],map_tex unicode "Rightarrow");
229                       Box.smallskip; 
230                       append_tail ~tail (Box.Object([],rhs))]) in
231         let plbox =
232           match pl with
233           | [] -> append_tail ~tail (Box.Text([],"[]"))
234           | [r] -> (make_rule ~tail:("]" :: tail) "[" r)
235           | r::tl -> 
236               Box.V([],
237                 (make_rule ~tail:[] "[" r) ::
238                 (make_args
239                   (fun ~tail pat -> make_rule ~tail "|" pat)
240                   ~tail:("]" :: tail)
241                   tl))
242         in
243         let ty_box =
244           match ty with
245           | Some ty ->
246               [ Box.H([],[Box.Text([],"[");
247                          ast2box ~tail:[] ty;
248                          Box.Text([],"]")]) ]
249           | None -> []
250         in
251         if is_big arg then
252           Box.V(make_attributes [Some "helm","xref"] [xref],
253                  ty_box @
254                  [Box.Text([],"match");
255                  Box.indent (Box.H([],[Box.skip; bigast2box ~tail:[] arg]));
256                  Box.Text([],"with");
257                  Box.indent plbox])
258         else
259           Box.V(make_attributes [Some "helm","xref"] [xref],
260                 ty_box @
261                 [Box.H(make_attributes [Some "helm","xref"] [xref],
262                        [Box.Text([],"match");
263                         Box.smallskip;
264                         ast2box ~tail:[] arg;
265                         Box.smallskip;
266                         Box.Text([],"with")]);
267                  Box.indent plbox])
268     | A.LetIn (var, s, t) ->
269         Box.V(make_attributes [Some "helm","xref"] [xref],
270               (make_def "let" var s "in")@[ast2box ~tail t])
271     | A.LetRec (_, vars, body) ->
272         let definitions =
273           let rec make_defs let_txt = function
274               [] -> []
275             | [(var,s,_)] -> make_def let_txt var s "in"
276             | (var,s,_)::tl ->
277                 (make_def let_txt var s "")@(make_defs "and" tl) in
278           make_defs "let rec" vars in
279         Box.V(make_attributes [Some "helm","xref"] [xref],
280               definitions@[ast2box ~tail body])
281     | A.Ident (s, subst)
282     | A.Uri (s, subst) ->
283         let subst =
284           let rec make_substs start_txt = 
285             function
286               [] -> []
287             | [(s,t)] -> 
288                 make_subst start_txt s t ""
289             | (s,t)::tl ->
290                 (make_subst start_txt s t ";")@(make_substs "" tl)
291           in
292           match subst with
293           | Some subst ->
294               Box.H([],
295                     [Box.Text(make_std_attributes xref,s);
296                      Box.Action([],
297                        [Box.Text([],"[...]");
298                         Box.H([], [Box.Text([], map_tex unicode "subst" ^ "[");
299                          Box.V([], make_substs "" subst);
300                          Box.Text([], "]")])])])
301           | None -> Box.Text(make_std_attributes xref, s)
302         in
303          subst
304         (*
305         Box.H([], (* attr here or on Vbox? *)
306               [Box.Text(make_std_attributes xref,s);
307                Box.Action([], [Box.Text([], "[_]"); Box.V([],subst)])])
308                (* Box.indent(Box.V([],subst))]) *)
309         *)
310     | A.Implicit -> 
311         Box.Text([],"_") (* big? *)
312     | A.Meta (n, l) ->
313         let local_context =
314           List.map 
315             (function t -> 
316                Box.H([],[aux_option ~tail t; Box.Text([],";")])) 
317             l in
318         Box.V(make_attributes [Some "helm","xref"] [xref],
319               [Box.Text([],"?"^(string_of_int n));
320                Box.H([],[Box.Text([],"[");
321                          Box.V([],local_context);
322                          Box.Text([],"]")])])
323     | A.Num (s, _) -> 
324          Box.Text([],s)
325     | A.Sort kind ->
326         (match kind with 
327              `Prop -> Box.Text([],"Prop")
328            | `Set -> Box.Text([],"Set")
329            | `Type -> Box.Text([],"Type")   
330            | `CProp -> Box.Text([],"CProp"))    
331     | A.Symbol (s, _) -> 
332         Box.Text([],s)
333
334     | A.UserInput -> Box.Text([],"")
335
336   and aux_option ~tail = function
337       None  -> Box.Text([],"_")
338     | Some ast -> ast2box ~tail ast 
339
340   and make_var ~tail = function
341       (Cic.Anonymous, None) -> Box.Text([],"_:_")
342     | (Cic.Anonymous, Some t) -> 
343         Box.H([],[Box.Text([],"_:");ast2box ~tail t])
344     | (Cic.Name s, None) -> Box.Text([],s)
345     | (Cic.Name s, Some t) ->
346         if is_big t then
347           Box.V([],[Box.Text([],s^":");
348                     Box.indent(bigast2box ~tail t)])
349         else
350           Box.H([],[Box.Text([],s^":");Box.Object([],t)])
351
352   and make_pattern constr = 
353     function
354         [] -> Box.Text([],constr)
355       | vars -> 
356           let bvars =
357             List.fold_right 
358               (fun var acc -> 
359                  let bv = 
360                    match var with
361                        (* ignoring the type *)
362                        (Cic.Anonymous, _) -> Box.Text([],"_")
363                      | (Cic.Name s, _) -> Box.Text([],s) in
364                    Box.Text([]," ")::bv::acc) vars [Box.Text([],")")] in
365             Box.H([],Box.Text([],"(")::Box.Text([],constr)::bvars)
366       
367
368   and make_def let_txt var def end_txt =
369     let name = 
370       (match var with
371            (* ignoring the type *)
372            (Cic.Anonymous, _) -> Box.Text([],"_") 
373          | (Cic.Name s, _) -> Box.Text([],s)) in
374     pretty_append ~tail:[end_txt]
375       [Box.Text([],let_txt);
376        Box.smallskip;
377        name;
378        Box.smallskip;
379        Box.Text([],"=")
380       ]
381       def 
382
383   and make_subst start_txt varname body end_txt =
384     pretty_append ~tail:[end_txt]
385       ((if start_txt <> "" then [Box.Text([],start_txt)] else [])@
386        [Box.Text([],varname);
387         Box.smallskip;
388         Box.Text([],map_tex unicode "Assign")
389        ])
390       body
391             
392   and pretty_append ~tail l ast =
393     if is_big ast then
394       [Box.H([],l);
395        Box.H([],[Box.skip; bigast2box ~tail ast])]
396     else
397       [Box.H([],l@[Box.smallskip; (ast2box ~tail ast)])]
398
399 in
400 ast2box ~priority ~assoc ~tail t
401 ;;
402
403 let m_row_with_fences = P.row_with_brackets
404 let m_row = P.row_without_brackets
405 let m_open_fence = P.Mo([None, "stretchy", "false"], "(")
406 let m_close_fence = P.Mo([None, "stretchy", "false"], ")")
407
408 let ast2mpres ?(priority = 0) ?(assoc = false) (ast, ids_to_uris) =
409   let lookup_uri = function
410     | None -> None
411     | Some id ->
412         (try
413           Some (Hashtbl.find ids_to_uris id)
414         with Not_found -> None)
415   in
416   let make_std_attributes xref =
417     let uri = lookup_uri xref in
418     make_attributes [Some "helm","xref"; Some "xlink","href"] [xref;uri]
419   in
420   let rec aux ?xref =
421   function
422     | A.AttributedTerm (`Loc _, ast) -> aux ?xref ast
423     | A.AttributedTerm (`IdRef xref, ast) -> aux ~xref ast
424     | A.Symbol (name,_) -> 
425         let attr = make_std_attributes xref in
426         P.Mi (attr,name)
427     | A.Ident (name,subst)
428     | A.Uri (name,subst) ->
429         let attr = make_std_attributes xref in
430         let rec make_subst =
431           (function 
432               [] -> []
433             | (n,a)::tl ->
434                 (aux a)::
435                 P.Mtext([],"/")::
436                 P.Mi([],n)::
437                 P.Mtext([],"; ")::
438                 P.smallskip::
439                 (make_subst tl)) in
440         let subst =
441           match subst with
442           | None -> []
443           | Some subst -> make_subst subst
444         in
445         (match subst with
446         | [] -> P.Mi (attr, name)
447         | _ ->
448             P.Mrow ([],
449               P.Mi (attr,name)::
450               P.Mtext([],"[")::
451               subst @
452               [(P.Mtext([],"]"))]))
453     | A.Meta (no,l) ->
454         let attr = make_attributes [Some "helm","xref"] [xref] in
455         let l' =
456          List.map
457           (function
458               None -> P.Mo([],"_")
459             | Some t -> aux t
460           ) l
461         in
462          P.Mrow ([],P.Mi (attr,"?" ^ string_of_int no) :: P.Mo ([],"[") ::
463            l' @ [P.Mo ([],"]")])
464     | A.Num (value, _) -> 
465         let attr = make_attributes [Some "helm","xref"] [xref] in
466         P.Mn (attr,value)
467     | A.Sort `Prop -> P.Mtext ([], "Prop")
468     | A.Sort `Set -> P.Mtext ([], "Set")
469     | A.Sort `Type -> P.Mtext ([], "Type")
470     | A.Sort `CProp -> P.Mtext ([], "CProp")
471     | A.Implicit -> P.Mtext([], "?")
472     | A.UserInput -> P.Mtext([], "")
473     | A.Appl [] -> assert false
474     | A.Appl ((hd::tl) as l) ->
475         let aattr = make_attributes [Some "helm","xref"] [xref] in
476         (match find_symbol None hd with
477         | `Symbol (name, sxref) ->
478             let sattr = make_std_attributes sxref in
479             (try 
480               (let f = Hashtbl.find symbol_table name in
481                f tl ~priority ~assoc ~ids_to_uris aattr sattr)
482             with Not_found ->
483               P.Mrow(aattr,
484               m_open_fence :: P.Mi(sattr,name)::(make_args tl) @
485               [m_close_fence]))
486         | `None ->
487             P.Mrow(aattr, m_open_fence :: (aux hd) :: (make_args tl) @
488             [m_close_fence]))
489     | A.Binder (`Pi, (Cic.Anonymous, Some ty), body)
490     | A.Binder (`Forall, (Cic.Anonymous, Some ty), body) ->
491         let attr = make_attributes [Some "helm","xref"] [xref] in
492         P.Mrow (attr, [
493           aux ty;
494           P.Mtext ([], map_tex true "to");
495           aux body])
496     | A.Binder (kind,var,body) ->
497         let attr = make_attributes [Some "helm","xref"] [xref] in
498         let binder = resolve_binder true kind in
499         let var = make_capture_variable var in
500         P.Mrow (attr, 
501            P.Mtext([None,"mathcolor","blue"],binder) :: var @ 
502            [P.Mo([],"."); aux body])
503     | A.LetIn (var,s,body) ->
504         let attr = make_attributes [Some "helm","xref"] [xref] in
505         P.Mrow (attr, 
506            P.Mtext([],("let ")) ::
507            (make_capture_variable var @
508            P.Mtext([],("="))::
509            (aux s)::
510            P.Mtext([]," in ")::
511            [aux body]))
512     | A.LetRec (_, defs, body) ->
513         let attr = make_attributes [Some "helm","xref"] [xref] in
514         let rec make_defs =
515           (function 
516                [] -> assert false
517              | [(var,body,_)] -> 
518                  make_capture_variable var @ [P.Mtext([],"=");(aux body)]
519              | (var,body,_)::tl -> 
520                  make_capture_variable var @
521                  (P.Mtext([],"=")::
522                   (aux body)::P.Mtext([]," and")::(make_defs tl))) in
523         P.Mrow (attr,  
524           P.Mtext([],("let rec "))::
525           (make_defs defs)@
526            (P.Mtext([]," in ")::
527            [aux body]))
528     | A.Case (arg,_,outtype,patterns) ->
529         (* TODO print outtype *)
530         let attr = make_attributes [Some "helm","xref"] [xref] in
531         let rec make_patterns =
532           (function 
533                [] -> []
534              | [(constr, vars),rhs] -> make_pattern constr vars rhs
535              | ((constr,vars), rhs)::tl -> 
536                  (make_pattern constr vars rhs)@(P.smallskip::
537                  P.Mtext([],"|")::P.smallskip::(make_patterns tl)))
538         and make_pattern constr vars rhs =           
539           let lhs = 
540             P.Mtext([], constr) ::
541               (List.concat
542                 (List.map
543                   (fun var -> P.smallskip :: make_capture_variable var)
544                   vars))
545           in
546           lhs @
547           [P.smallskip; P.Mtext([],map_tex true "to"); P.smallskip; aux rhs]
548         in
549         P.Mrow (attr,
550           P.Mtext([],"match")::P.smallskip::
551           (aux arg)::P.smallskip::
552           P.Mtext([],"with")::P.smallskip::
553           P.Mtext([],"[")::P.smallskip::
554           (make_patterns patterns)@(P.smallskip::[P.Mtext([],("]"))]))
555
556   and make_capture_variable (name, ty) =
557     let name =
558       match name with
559       | Cic.Anonymous -> [P.Mtext([], "_")]
560       | Cic.Name s -> [P.Mtext([], s)]
561     in
562     let ty =
563       match ty with
564       | None -> []
565       | Some ty -> [P.Mtext([],":"); aux ty]
566     in
567     name @ ty
568
569   and make_args ?(priority = 0) ?(assoc = false) =
570     function
571         [] -> []
572       | a::tl -> P.smallskip::(aux a)::(make_args tl)
573
574   in
575   aux ast
576 ;;
577
578 let box_prefix = "b";;
579
580 let add_xml_declaration stream =
581   [<
582     Xml.xml_cdata "<?xml version=\"1.0\" ?>\n" ;
583     Xml.xml_cdata "\n";
584     Xml.xml_nempty ~prefix:box_prefix "box"
585       [ Some "xmlns","m","http://www.w3.org/1998/Math/MathML" ;
586         Some "xmlns","b","http://helm.cs.unibo.it/2003/BoxML" ;
587         Some "xmlns","helm","http://www.cs.unibo.it/helm" ;
588         Some "xmlns","xlink","http://www.w3.org/1999/xlink"
589       ] stream
590   >]
591
592 let ast2mpresXml ((ast, ids_to_uris) as arg) =
593   let astBox = ast2astBox arg in
594   let smallAst2mpresXml ast =
595     P.print_mpres (fun _ -> assert false) (ast2mpres (ast, ids_to_uris))
596   in
597   (Box.box2xml ~obj2xml:smallAst2mpresXml astBox)
598
599 let b_open_fence = Box.b_text [] "("
600 let b_close_fence = Box.b_text [] ")"
601 let b_v_with_fences attrs a b op =
602   Box.b_h attrs [
603     b_open_fence;
604     Box.b_v [] [
605       a;
606       Box.b_h [] [ op; b ]
607     ];
608     b_close_fence
609   ]
610 let b_v_without_fences attrs a b op =
611   Box.b_v attrs [
612     a;
613     Box.b_h [] [ op; b ]
614   ]
615
616 let _ = (** fill symbol_table *)
617   let binary f = function [a;b] -> f a b | _ -> assert false in
618   let unary f = function [a] -> f a | _ -> assert false in
619   let add_binary_op name threshold ?(assoc=`Left) symbol =
620     let assoc = match assoc with `Left -> true | `Right -> false in
621     Hashtbl.add symbol_table name (binary
622       (fun a b ~priority ~assoc ~ids_to_uris aattr sattr ->
623         let symbol =
624           match symbol with
625           | `Symbol name -> map_tex true name
626           | `Ascii s -> s
627         in
628          if (priority > threshold) || (priority = threshold && assoc) then
629            m_row_with_fences aattr
630              (ast2mpres ~priority:threshold ~assoc (a, ids_to_uris))
631              (ast2mpres ~priority:threshold ~assoc:(not assoc) (b, ids_to_uris))
632              (P.Mo(sattr,symbol))
633          else 
634            m_row aattr
635              (ast2mpres ~priority:threshold ~assoc (a, ids_to_uris))
636              (ast2mpres ~priority:threshold ~assoc:(not assoc) (b, ids_to_uris))
637              (P.Mo(sattr,symbol))));
638     Hashtbl.add symbol_table_charcount name (binary
639       (fun a b ~unicode ~priority ~assoc ~tail ~ids_to_uris aattr sattr ->
640         let symbol =
641           match symbol with
642           | `Symbol name -> map_tex unicode name
643           | `Ascii s -> s
644         in
645
646          if (priority > threshold) || (priority = threshold && assoc) then
647            b_v_with_fences aattr
648              (ast2astBox ~priority:threshold ~assoc ~tail:[] (a, ids_to_uris))
649              (ast2astBox ~priority:threshold ~assoc:(not assoc) ~tail
650               (b, ids_to_uris))
651              (Box.Text(sattr,symbol))
652          else 
653            b_v_without_fences aattr
654              (ast2astBox ~priority:threshold ~assoc ~tail:[] (a, ids_to_uris))
655              (ast2astBox ~priority:threshold ~assoc:(not assoc) ~tail
656               (b, ids_to_uris))
657              (Box.Text(sattr,symbol))))
658   in
659   Hashtbl.add symbol_table "not" (unary
660     (fun a ~priority ~assoc ~ids_to_uris attr sattr ->
661        (P.Mrow([], [
662          m_open_fence; P.Mo([],map_tex true "lnot");
663          ast2mpres (a, ids_to_uris); m_close_fence]))));
664   Hashtbl.add symbol_table "inv" (unary
665     (fun a ~priority ~assoc ~ids_to_uris attr sattr ->
666       P.Msup([],
667         P.Mrow([],[ m_open_fence; ast2mpres (a, ids_to_uris); m_close_fence]),
668         P.Mrow([],[ P.Mo([],"-"); P.Mn([],"1")]))));
669   Hashtbl.add symbol_table "opp" (unary
670     (fun a ~priority ~assoc ~ids_to_uris attr sattr ->
671       P.Mrow([],[
672         P.Mo([],"-");
673         m_open_fence;
674         ast2mpres (a, ids_to_uris);
675         m_close_fence])));
676   add_binary_op "arrow" 5 ~assoc:`Right (`Symbol "to");
677   add_binary_op "eq" 40 (`Ascii "=");
678   add_binary_op "and" 20 (`Symbol "land");
679   add_binary_op "or" 10 (`Symbol "lor");
680   add_binary_op "iff" 5 (`Symbol "iff");
681   add_binary_op "leq" 40 (`Symbol "leq");
682   add_binary_op "lt" 40 (`Symbol "lt");
683   add_binary_op "geq" 40 (`Symbol "geq");
684   add_binary_op "gt" 40 (`Symbol "gt");
685   add_binary_op "plus" 60 (`Ascii "+");
686   add_binary_op "times" 70 (`Ascii "*");
687   add_binary_op "minus" 60 (`Ascii "-");
688   add_binary_op "div" 60 (`Ascii "/");
689   add_binary_op "cast" 80 (`Ascii ":");
690