1 (* Copyright (C) 2005, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://helm.cs.unibo.it/
30 let rec flatten_tree = function
33 | Node {node = n; brother = b; son = s} ->
34 List.map (fun l -> n :: l) (flatten_tree s) @ flatten_tree b
36 let tex_of_unicode s = s
38 let rec clean_dummy_desc = function
39 | Dlevels l -> Dlevels (clean_levels l)
42 and clean_levels = function
44 | l :: tl -> clean_level l @ clean_levels tl
46 and clean_level = function
48 let pref = clean_tree x.lprefix in
49 let suff = clean_tree x.lsuffix in
51 | DeadEnd, DeadEnd -> []
52 | _ -> [{x with lprefix = pref; lsuffix = suff}]
54 and clean_tree = function
55 | Node n -> clean_node n
58 and clean_node = function
59 | {node=node;son=son;brother=brother} ->
60 let bn = is_symbol_dummy node in
61 let bs = is_tree_dummy son in
62 let bb = is_tree_dummy brother in
63 let son = if bs then DeadEnd else son in
64 let brother = if bb then DeadEnd else brother in
65 if bb && bs && bn then
69 Node {node=Sself;son=son;brother=brother}
71 Node {node=node;son=son;brother=brother}
73 and is_level_dummy = function
74 | {lsuffix=lsuffix;lprefix=lprefix} ->
75 is_tree_dummy lsuffix && is_tree_dummy lprefix
77 and is_desc_dummy = function
78 | Dlevels l -> List.for_all is_level_dummy l
81 and is_entry_dummy = function
82 | {edesc=edesc} -> is_desc_dummy edesc
84 and is_symbol_dummy = function
85 | Stoken ("DUMMY", _) -> true
87 | Smeta (_, lt, _) -> List.for_all is_symbol_dummy lt
88 | Snterm e | Snterml (e, _) -> is_entry_dummy e
89 | Slist1 x | Slist0 x -> is_symbol_dummy x
90 | Slist1sep (x,y,false) | Slist0sep (x,y,false) -> is_symbol_dummy x && is_symbol_dummy y
91 | Sopt x -> is_symbol_dummy x
92 | Sself | Snext -> false
93 | Stree t -> is_tree_dummy t
96 and is_tree_dummy = function
97 | Node {node=node} -> is_symbol_dummy node
100 let needs_brackets t =
101 let rec count_brothers = function
102 | Node {brother = brother} -> 1 + count_brothers brother
107 let visit_description desc fmt self =
109 let inline s = List.mem s [ "int" ] in
111 let rec visit_entry e ?level todo is_son =
112 let { ename = ename; edesc = desc } = e in
114 visit_desc desc todo is_son
118 | None -> Format.fprintf fmt "%s " ename;
119 | Some _ -> Format.fprintf fmt "%s " ename;);
126 and visit_desc d todo is_son =
131 Format.fprintf fmt "@ ";
132 visit_level l acc is_son )
136 and visit_level l todo is_son =
137 let { lname = name ; lsuffix = suff ; lprefix = pref } = l in
140 (fun x -> Sself :: x) (flatten_tree suff) @ flatten_tree pref)
143 and visit_tree name t todo is_son =
144 if List.for_all (List.for_all is_symbol_dummy) t then todo else (
145 Format.fprintf fmt "@[<v>";
147 |Some name -> Format.fprintf fmt "Precedence %s:@ " name
149 Format.fprintf fmt "@[<v>";
153 if List.for_all is_symbol_dummy x then todo else (
154 Format.fprintf fmt "@[<h> | ";
158 let todo = visit_symbol x acc true in
159 Format.fprintf fmt "@ ";
163 Format.fprintf fmt "@]@ ";
167 Format.fprintf fmt "@]";
168 Format.fprintf fmt "@]";
171 and visit_symbol s todo is_son =
173 | Smeta (name, sl, _) ->
174 Format.fprintf fmt "%s " name;
177 let todo = visit_symbol s acc is_son in
179 Format.fprintf fmt "@ ";
182 | Snterm entry -> visit_entry entry todo is_son
183 | Snterml (entry,level) -> visit_entry entry ~level todo is_son
185 Format.fprintf fmt "{@[<hov2> ";
186 let todo = visit_symbol symbol todo is_son in
187 Format.fprintf fmt "@]} @ ";
189 | Slist0sep (symbol,sep,false) ->
190 Format.fprintf fmt "[@[<hov2> ";
191 let todo = visit_symbol symbol todo is_son in
192 Format.fprintf fmt "{@[<hov2> ";
193 let todo = visit_symbol sep todo is_son in
194 Format.fprintf fmt " ";
195 let todo = visit_symbol symbol todo is_son in
196 Format.fprintf fmt "@]} @]] @ ";
199 Format.fprintf fmt "{@[<hov2> ";
200 let todo = visit_symbol symbol todo is_son in
201 Format.fprintf fmt "@]}+ @ ";
203 | Slist1sep (symbol,sep,false) ->
204 let todo = visit_symbol symbol todo is_son in
205 Format.fprintf fmt "{@[<hov2> ";
206 let todo = visit_symbol sep todo is_son in
207 let todo = visit_symbol symbol todo is_son in
208 Format.fprintf fmt "@]} @ ";
211 Format.fprintf fmt "[@[<hov2> ";
212 let todo = visit_symbol symbol todo is_son in
213 Format.fprintf fmt "@]] @ ";
215 | Sself -> Format.fprintf fmt "%s " self; todo
216 | Snext -> Format.fprintf fmt "next "; todo
218 let constructor, keyword = pattern in
220 (if constructor <> "DUMMY" then
221 Format.fprintf fmt "`%s' " constructor)
223 Format.fprintf fmt "%s " (tex_of_unicode keyword);
226 visit_tree None (flatten_tree tree) todo is_son
229 visit_desc desc [] false
233 let rec visit_entries fmt todo pped =
238 if not (List.memq hd pped) then
240 let { ename = ename; edesc = desc } = hd in
241 Format.fprintf fmt "@[<hv 2>%s ::= " ename;
242 let desc = clean_dummy_desc desc in
243 let todo = visit_description desc fmt ename @ todo in
244 Format.fprintf fmt "@]\n\n";
250 let clean_todo todo =
251 let name_of_entry e = e.ename in
252 let pped = hd :: pped in
253 let todo = tl @ todo in
254 let todo = List.filter (fun e -> not(List.memq e pped)) todo in
256 ~eq:(fun e1 e2 -> (name_of_entry e1) = (name_of_entry e2))
259 Pervasives.compare (name_of_entry e1) (name_of_entry e2))
263 let todo,pped = clean_todo todo in
264 visit_entries fmt todo pped
267 let ebnf_of_term status =
268 let g_entry = Grammar.Entry.obj (CicNotationParser.term status) in
269 let buff = Buffer.create 100 in
270 let fmt = Format.formatter_of_buffer buff in
271 visit_entries fmt [g_entry] [];
272 Format.fprintf fmt "@?";
273 let s = Buffer.contents buff in