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