]> matita.cs.unibo.it Git - helm.git/blob - matitaB/components/content_pres/cicNotationPres.ml
7f1470f76d8f44935ec8a9d1ff1c192a6a8acaf5
[helm.git] / matitaB / components / content_pres / cicNotationPres.ml
1 (* Copyright (C) 2004-2005, 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://helm.cs.unibo.it/
24  *)
25
26 open Printf
27
28 module A = NotationPt
29
30 type markup = string Box.box
31
32 let to_unicode = Utf8Macro.unicode_of_tex
33
34 let small_skip    = Box.Text ([], " ")
35 let open_paren    = Box.Text ([], "(")
36 let closed_paren  = Box.Text ([], ")")
37 let semicolon     = Box.Text ([], ";")
38
39 let toggle_action children =
40   Box.Action ([None, "actiontype", "toggle"], children)
41
42 type child_pos = [ `Left | `Right | `Inner ]
43
44 let pp_assoc =
45   function
46   | Gramext.LeftA -> "LeftA"
47   | Gramext.RightA -> "RightA"
48   | Gramext.NonA -> "NonA"
49
50 let rec is_atomic = function
51   | Box.Space _
52   | Box.Ink _
53   | Box.Text _ 
54   | Box.Object _ -> true
55   | Box.H (_, [box])
56   | Box.V (_, [box])
57   | Box.HV (_, [box])
58   | Box.HOV (_, [box])
59   | Box.Action (_, [box]) -> is_atomic box
60   | _ -> false
61
62 let add_parens child_prec curr_prec t =
63   if is_atomic t then 
64     ((*prerr_endline ("NOT adding parens around ATOMIC: "^
65       BoxPp.render_to_string (function x::_->x|_->assert false)
66         ~map_unicode_to_tex:false 80 t);*)t)
67   else if child_prec >= 0 && child_prec < curr_prec then 
68     begin 
69     (*prerr_endline ("adding parens around: "^
70       BoxPp.render_to_string (function x::_->x|_->assert false)
71         ~map_unicode_to_tex:false 80 t);*)
72       Box.H ([], [ open_paren; t; closed_paren ])
73   end else
74     ((*prerr_endline ("NOT adding parens around: "^
75       BoxPp.render_to_string (function x::_->x|_->assert false)
76         ~map_unicode_to_tex:false 80 t);*)t)
77
78 let box_of spec attrs children =
79   match children with
80     | [t] -> t
81     | _ ->
82         let kind, spacing, indent = spec in
83         let dress children =
84           if spacing then
85             NotationUtil.dress small_skip children
86           else
87             children
88         in
89         let attrs' =
90           (if spacing then [None, "spacing", "0.5em"] else [])
91           @ (if indent then [None, "indent", "0.5em"] else []) 
92           @ attrs
93         in
94           match kind with
95             | A.H -> Box.H (attrs',children)
96             | A.V -> Box.V (attrs',children)
97             | A.HV -> Box.HV (attrs',children)
98             | A.HOV -> Box.HOV (attrs',children)
99
100 let render status ?(prec=(-1)) =
101   let rec aux prec t =
102     match t with
103     | A.AttributedTerm _ ->
104         aux_attributes [] ""  prec t
105     | A.Num (literal, _) -> Box.Text ([], literal)
106     | A.Symbol (literal, Some (None,desc)) -> 
107         let txt = "<A title=\"" ^ desc ^ "\">" ^ literal ^ "</A>" in 
108                     Box.Text ([], to_unicode txt)
109     | A.Symbol (literal, Some (Some u,desc)) -> 
110         let txt = 
111          "<A href=\"" ^ u ^ "\" title=\"" ^ desc ^ "\">" ^ literal ^ "</A>" in
112         Box.Text ([], to_unicode txt)
113     | A.Symbol (literal, _) -> Box.Text ([], to_unicode literal)
114     | A.Ident (literal, `Uri u) ->
115         let txt = "<A href=\"" ^ u ^ "\">" ^ literal ^ "</A>" in 
116         Box.Text ([], to_unicode txt)
117     | A.Ident (literal, _) -> Box.Text ([], to_unicode literal)
118     | A.Meta(n, l) ->
119         let local_context =
120           Box.Text ([], "["):: 
121             (NotationUtil.dress (Box.Text ([],  ";"))
122               (List.map 
123                 (function 
124                 | None -> Box.Text ([],  "_")
125                 | Some t -> aux prec t) l)) @
126             [Box.Text ([], "]")]
127         in
128         Box.H ([],
129           (Box.Text ([], "?"^string_of_int n)::
130             (if (l <> []) then [Box.H ([],local_context)] else [])))
131     | A.Literal l -> aux_literal prec l
132     | A.UserInput -> Box.Text ([], "%")
133     | A.Layout l -> aux_layout prec l
134     | A.Magic _
135     | A.Variable _ -> assert false  (* should have been instantiated *)
136     | t ->
137         prerr_endline ("unexpected ast: " ^ NotationPp.pp_term status t);
138         assert false
139
140   and aux_attributes xmlattrs xref  prec t =
141     let reset = ref false in
142     let inferred_level = ref None in
143     let expected_level = ref None in
144     let new_xref = ref [] in
145     let new_xmlattrs = ref [] in
146     let rec aux_attribute =
147       function
148       | A.AttributedTerm (attr, t) ->
149           (match attr with
150           | `Loc _
151           | `Raw _ -> ()
152           | `Level (-1) -> reset := true
153           | `Level child_prec ->
154 (*               assert (!expected_level = None); *)
155               expected_level := !inferred_level;
156               inferred_level := Some child_prec
157           | `IdRef xref -> new_xref := xref :: !new_xref
158           | `XmlAttrs attrs -> new_xmlattrs := attrs @ !new_xmlattrs);
159           aux_attribute t
160       | t ->
161           let prec = 
162             match !expected_level with
163             | None -> prec
164             | Some prec -> prec
165           in
166           (match !inferred_level with
167           | None -> aux prec t
168           | Some child_prec ->
169               let t' = aux child_prec t in
170               (*prerr_endline 
171                 ("inferred: "^string_of_int child_prec^ 
172                  " exp: "^string_of_int prec ^ 
173                  " term: "^BoxPp.render_to_string ~map_unicode_to_tex:false
174                     (function x::_->x|_->assert false) 80 t');*)
175               if !reset
176               then ((*prerr_endline "reset";*)t')
177               else add_parens child_prec prec t')
178     in
179 (*     prerr_endline (NotationPp.pp_term t); *)
180     aux_attribute t
181
182   and aux_literal prec l =
183     (match l with
184     | `Symbol s -> Box.Text ([], to_unicode s)
185     | `Keyword s -> Box.Text ([], to_unicode s)
186     | `Number s  -> Box.Text ([], to_unicode s))
187
188   and aux_layout prec l =
189     let attrs = [] in
190     let invoke' t = aux prec t in
191       (* use the one below to reset precedence and associativity *)
192     let invoke_reinit t = aux ~-1 t in
193     match l with
194     | A.Sup (A.Layout (A.Sub (t1,t2)), t3)
195     | A.Sup (A.AttributedTerm (_,A.Layout (A.Sub (t1,t2))), t3)
196       -> assert false
197     | A.Sub (t1, t2) -> Box.H ([],[aux prec t1;Box.Text ([],"_");aux prec t2])
198     | A.Sup (t1, t2) -> Box.H ([],[aux prec t1;Box.Text ([],"^");aux prec t2])
199     | A.Below (t1, t2) -> assert false 
200     | A.Above (t1, t2) -> assert false
201     | A.Frac (t1, t2)
202     | A.Over (t1, t2) -> assert false
203     | A.Atop (t1, t2) -> assert false
204     | A.InfRule (t1, t2, t3) -> assert false
205     | A.Sqrt t -> assert false
206     | A.Root (t1, t2) -> assert false
207     | A.Box ((_,spacing,_) as kind, terms) ->
208         let children =
209           aux_children spacing prec
210             (NotationUtil.ungroup terms)
211         in
212         box_of kind attrs children
213     | A.Mstyle (l,terms) -> assert false
214     | A.Mpadded (l,terms) -> assert false
215     | A.Maction alternatives -> 
216          toggle_action (List.map invoke_reinit alternatives)
217     | A.Group terms -> assert false 
218     | A.Break -> Box.Space []
219   and aux_children spacing prec terms =
220     let find_clusters =
221       let rec aux_list first clusters acc =
222         function
223             [] when acc = [] -> List.rev clusters
224           | [] -> aux_list first (List.rev acc :: clusters) [] []
225           | (A.Layout A.Break) :: tl when acc = [] ->
226               aux_list first clusters [] tl
227           | (A.Layout A.Break) :: tl ->
228               aux_list first (List.rev acc :: clusters) [] tl
229           | [hd] ->
230                 aux_list false clusters
231                   (aux prec hd :: acc) []
232           | hd :: tl ->
233                 aux_list false clusters
234                   (aux prec hd :: acc) tl
235       in
236         aux_list true [] []
237     in
238     let boxify_pres =
239       function
240           [t] -> t
241         | tl -> box_of (A.H, spacing, false) [] tl
242     in
243       List.map boxify_pres (find_clusters terms) 
244   in
245   (fun t ->
246           prerr_endline ("ast:\n" ^ (NotationPp.pp_term status t));
247   aux prec t)
248
249 (* let render_to_boxml id_to_uri t =
250   let xml_stream = print_box (box_of_mpres (render id_to_uri t)) in
251   Xml.add_xml_declaration xml_stream *)
252
253 let render_context_entry status name = function
254   | A.Decl t -> 
255       Box.H ([],
256              [Box.Text([],name); Box.Text([],":"); 
257               render status (TermContentPres.pp_ast status t)])
258   | A.Def (t,ty) -> 
259       Box.H ([],
260               [Box.Text([],name); Box.Text([],Utf8Macro.unicode_of_tex"\\def");
261                render status (TermContentPres.pp_ast status t)])
262
263 let render_context status context =
264   Box.V ([], 
265          Box.Space [None, "width", "0.5em"]:: 
266          List.map 
267            (fun (name,entry) -> 
268               render_context_entry status (to_unicode name) entry) context)
269
270 let render_sequent status (i,context,ty) =
271   Box.V ([],
272          [render_context status (List.rev context);
273           Box.Ink [None,"width","4cm"; None,"height","2px"];
274           render status (TermContentPres.pp_ast status ty)])
275           
276