1 (* Copyright (C) 2004-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/
27 let debug_print s = if debug then prerr_endline (Lazy.force s)
31 (* ZACK TODO element from the DTD still to be handled:
32 <!ELEMENT CurrentProof (Conjecture*,body)>
33 <!ELEMENT Sequent %sequent;>
34 <!ELEMENT Conjecture %sequent;>
35 <!ELEMENT Decl %term;>
37 <!ELEMENT Hidden EMPTY>
38 <!ELEMENT Goal %term;>
41 exception Getter_failure of string * string
42 exception Parser_failure of string
45 | Arg of string * Cic.annterm (* relative uri, term *)
46 (* constants' body and types resides in differne files, thus we can't simple
47 * keep constants in Cic_obj stack entries *)
48 | Cic_attributes of Cic.attribute list
49 | Cic_constant_body of string * string * UriManager.uri list * Cic.annterm
51 (* id, for, params, body, object attributes *)
52 | Cic_constant_type of string * string * UriManager.uri list * Cic.annterm
54 (* id, name, params, type, object attributes *)
55 | Cic_term of Cic.annterm (* term *)
56 | Cic_obj of Cic.annobj (* object *)
57 | Cofix_fun of Cic.id * string * Cic.annterm * Cic.annterm
58 (* id, name, type, body *)
59 | Constructor of string * Cic.annterm (* name, type *)
60 | Decl of Cic.id * Cic.name * Cic.annterm (* id, binder, source *)
61 | Def of Cic.id * Cic.name * Cic.annterm (* id, binder, source *)
62 | Fix_fun of Cic.id * string * int * Cic.annterm * Cic.annterm
63 (* id, name, ind. index, type, body *)
64 | Inductive_type of string * string * bool * Cic.annterm *
65 (string * Cic.annterm) list (* id, name, inductive, arity, constructors *)
66 | Meta_subst of Cic.annterm option
67 | Obj_class of Cic.object_class
68 | Obj_flavour of Cic.object_flavour
69 | Obj_field of string (* field name *)
71 | Tag of string * (string * string) list (* tag name, attributes *)
72 (* ZACK TODO add file position to tag stack entry so that when attribute
73 * errors occur, the position of their _start_tag_ could be printed
74 * instead of the current position (usually the end tag) *)
77 mutable stack: stack_entry list;
78 mutable xml_parser: XmlPushParser.xml_parser option;
79 mutable filename: string;
83 let string_of_stack ctxt =
84 "[" ^ (String.concat "; "
87 | Arg (reluri, _) -> sprintf "Arg %s" reluri
88 | Cic_attributes _ -> "Cic_attributes"
89 | Cic_constant_body (id, name, _, _, _) ->
90 sprintf "Cic_constant_body %s (id=%s)" name id
91 | Cic_constant_type (id, name, _, _, _) ->
92 sprintf "Cic_constant_type %s (id=%s)" name id
93 | Cic_term _ -> "Cic_term"
94 | Cic_obj _ -> "Cic_obj"
95 | Constructor (name, _) -> "Constructor " ^ name
96 | Cofix_fun (id, _, _, _) -> sprintf "Cofix_fun (id=%s)" id
97 | Decl (id, _, _) -> sprintf "Decl (id=%s)" id
98 | Def (id, _, _) -> sprintf "Def (id=%s)" id
99 | Fix_fun (id, _, _, _, _) -> sprintf "Fix_fun (id=%s)" id
100 | Inductive_type (id, name, _, _, _) ->
101 sprintf "Inductive_type %s (id=%s)" name id
102 | Meta_subst _ -> "Meta_subst"
103 | Obj_class _ -> "Obj_class"
104 | Obj_flavour _ -> "Obj_flavour"
105 | Obj_field name -> "Obj_field " ^ name
106 | Obj_generated -> "Obj_generated"
107 | Tag (tag, _) -> "Tag " ^ tag)
110 let compare_attrs (a1, v1) (a2, v2) = Pervasives.compare a1 a2
111 let sort_attrs = List.sort compare_attrs
113 let new_parser_context uri = {
120 let get_parser ctxt =
121 match ctxt.xml_parser with
123 | None -> assert false
125 (** {2 Error handling} *)
127 let parse_error ctxt msg =
128 let (line, col) = XmlPushParser.get_position (get_parser ctxt) in
129 raise (Parser_failure (sprintf "[%s: line %d, column %d] %s"
130 ctxt.filename line col msg))
132 let attribute_error ctxt tag =
133 parse_error ctxt ("wrong attribute set for " ^ tag)
135 (** {2 Parsing context management} *)
138 (* debug_print (lazy "pop");*)
139 match ctxt.stack with
140 | hd :: tl -> (ctxt.stack <- tl)
144 (* debug_print (lazy "push");*)
145 ctxt.stack <- v :: ctxt.stack
148 (* debug_print (lazy "set_top");*)
149 match ctxt.stack with
150 | _ :: tl -> (ctxt.stack <- v :: tl)
153 (** pop the last tag from the open tags stack returning a pair <tag_name,
156 match ctxt.stack with
157 | Tag (tag, attrs) :: tl ->
160 | _ -> parse_error ctxt "unexpected extra content"
162 (** pop the last tag from the open tags stack returning its attributes.
163 * Attributes are returned as a list of pair <name, value> _sorted_ by
165 let pop_tag_attrs ctxt = sort_attrs (snd (pop_tag ctxt))
168 let rec aux acc stack =
170 | Cic_term t :: tl -> aux (t :: acc) tl
173 let values, new_stack = aux [] ctxt.stack in
174 ctxt.stack <- new_stack;
177 let pop_class_modifiers ctxt =
178 let rec aux acc stack =
180 | (Cic_term (Cic.ASort _) as m) :: tl
181 | (Obj_field _ as m) :: tl ->
185 let values, new_stack = aux [] ctxt.stack in
186 ctxt.stack <- new_stack;
189 let pop_meta_substs ctxt =
190 let rec aux acc stack =
192 | Meta_subst t :: tl -> aux (t :: acc) tl
195 let values, new_stack = aux [] ctxt.stack in
196 ctxt.stack <- new_stack;
199 let pop_fix_funs ctxt =
200 let rec aux acc stack =
202 | Fix_fun (id, name, index, typ, body) :: tl ->
203 aux ((id, name, index, typ, body) :: acc) tl
206 let values, new_stack = aux [] ctxt.stack in
207 ctxt.stack <- new_stack;
210 let pop_cofix_funs ctxt =
211 let rec aux acc stack =
213 | Cofix_fun (id, name, typ, body) :: tl ->
214 aux ((id, name, typ, body) :: acc) tl
217 let values, new_stack = aux [] ctxt.stack in
218 ctxt.stack <- new_stack;
221 let pop_constructors ctxt =
222 let rec aux acc stack =
224 | Constructor (name, t) :: tl -> aux ((name, t) :: acc) tl
227 let values, new_stack = aux [] ctxt.stack in
228 ctxt.stack <- new_stack;
231 let pop_inductive_types ctxt =
232 let rec aux acc stack =
234 | Inductive_type (id, name, ind, arity, ctors) :: tl ->
235 aux ((id, name, ind, arity, ctors) :: acc) tl
238 let values, new_stack = aux [] ctxt.stack in
240 parse_error ctxt "no \"InductiveType\" element found";
241 ctxt.stack <- new_stack;
244 (** travels the stack (without popping) for the first term subject of explicit
245 * named substitution and return its URI *)
246 let find_base_uri ctxt =
247 let rec aux = function
248 | Cic_term (Cic.AConst (_, uri, _)) :: _
249 | Cic_term (Cic.AMutInd (_, uri, _, _)) :: _
250 | Cic_term (Cic.AMutConstruct (_, uri, _, _, _)) :: _
251 | Cic_term (Cic.AVar (_, uri, _)) :: _ ->
253 | Arg _ :: tl -> aux tl
254 | _ -> parse_error ctxt "no \"arg\" element found"
256 UriManager.buri_of_uri (aux ctxt.stack)
258 (** backwardly eats the stack building an explicit named substitution from Arg
260 let pop_subst ctxt base_uri =
261 let rec aux acc stack =
263 | Arg (rel_uri, term) :: tl ->
264 let uri = UriManager.uri_of_string (base_uri ^ "/" ^ rel_uri) in
265 aux ((uri, term) :: acc) tl
268 let subst, new_stack = aux [] ctxt.stack in
270 parse_error ctxt "no \"arg\" element found";
271 ctxt.stack <- new_stack;
275 match ctxt.stack with
276 | Cic_term t :: tl ->
279 | _ -> parse_error ctxt "no cic term found"
281 let pop_obj_attributes ctxt =
282 match ctxt.stack with
283 | Cic_attributes attributes :: tl ->
288 (** {2 Auxiliary functions} *)
290 let uri_of_string = UriManager.uri_of_string
292 let uri_list_of_string =
293 let space_RE = Str.regexp " " in
295 List.map uri_of_string (Str.split space_RE s)
297 let sort_of_string ctxt = function
300 | "CProp" -> Cic.CProp
301 (* THIS CASE IS HERE ONLY TO ALLOW THE PARSING OF COQ LIBRARY
302 * THIS SHOULD BE REMOVED AS SOON AS univ_maker OR COQ'S EXPORTATION
304 | "Type" -> Cic.Type (CicUniv.fresh ~uri:ctxt.uri ())
306 let len = String.length s in
307 if not(len > 5) then parse_error ctxt "sort expected";
308 if not(String.sub s 0 5 = "Type:") then parse_error ctxt "sort expected";
313 ~id:(int_of_string (String.sub s 5 (len - 5))) ())
315 | Failure "int_of_string"
316 | Invalid_argument _ -> parse_error ctxt "sort expected"
318 let patch_subst ctxt subst = function
319 | Cic.AConst (id, uri, _) -> Cic.AConst (id, uri, subst)
320 | Cic.AMutInd (id, uri, typeno, _) ->
321 Cic.AMutInd (id, uri, typeno, subst)
322 | Cic.AMutConstruct (id, uri, typeno, consno, _) ->
323 Cic.AMutConstruct (id, uri, typeno, consno, subst)
324 | Cic.AVar (id, uri, _) -> Cic.AVar (id, uri, subst)
327 ("only \"CONST\", \"VAR\", \"MUTIND\", and \"MUTCONSTRUCT\" can be" ^
330 (** backwardly eats the stack seeking for the first open tag carrying
331 * "helm:exception" attributes. If found return Some of a pair containing
332 * exception name and argument. Return None otherwise *)
333 let find_helm_exception ctxt =
334 let rec aux = function
336 | Tag (_, attrs) :: tl ->
338 let exn = List.assoc "helm:exception" attrs in
340 try List.assoc "helm:exception_arg" attrs with Not_found -> ""
343 with Not_found -> aux tl)
348 (** {2 Push parser callbacks}
349 * each callback needs to be instantiated to a parsing context *)
351 let start_element ctxt tag attrs =
352 (* debug_print (lazy (sprintf "<%s%s>" tag (match attrs with | [] -> "" | _ -> " " ^ String.concat " " (List.map (fun (a,v) -> sprintf "%s=\"%s\"" a v) attrs))));*)
353 push ctxt (Tag (tag, attrs))
355 let end_element ctxt tag =
356 (* debug_print (lazy (sprintf "</%s>" tag));*)
357 (* debug_print (lazy (string_of_stack ctxt));*)
358 let attribute_error () = attribute_error ctxt tag in
359 let parse_error = parse_error ctxt in
360 let sort_of_string = sort_of_string ctxt in
364 (match pop_tag_attrs ctxt with
365 | ["binder", binder; "id", id; "idref", idref; "value", value]
366 | ["binder", binder; "id", id; "idref", idref; "sort", _;
368 Cic.ARel (id, idref, int_of_string value, binder)
369 | _ -> attribute_error ()))
372 (match pop_tag_attrs ctxt with
373 | ["id", id; "uri", uri]
374 | ["id", id; "sort", _; "uri", uri] ->
375 Cic.AVar (id, uri_of_string uri, [])
376 | _ -> attribute_error ()))
379 (match pop_tag_attrs ctxt with
380 | ["id", id; "uri", uri]
381 | ["id", id; "sort", _; "uri", uri] ->
382 Cic.AConst (id, uri_of_string uri, [])
383 | _ -> attribute_error ()))
386 (match pop_tag_attrs ctxt with
387 | ["id", id; "value", sort] -> Cic.ASort (id, sort_of_string sort)
388 | _ -> attribute_error ()))
390 let args = pop_cics ctxt in
392 (match pop_tag_attrs ctxt with
394 | ["id", id; "sort", _] -> Cic.AAppl (id, args)
395 | _ -> attribute_error ()))
397 let source = pop_cic ctxt in
399 (match pop_tag_attrs ctxt with
400 | ["binder", binder; "id", id ]
401 | ["binder", binder; "id", id; "type", _] ->
402 Decl (id, Cic.Name binder, source)
404 | ["id", id; "type", _] -> Decl (id, Cic.Anonymous, source)
405 | _ -> attribute_error ())
406 | "def" -> (* same as "decl" above *)
407 let source = pop_cic ctxt in
409 (match pop_tag_attrs ctxt with
410 | ["binder", binder; "id", id]
411 | ["binder", binder; "id", id; "sort", _] ->
412 Def (id, Cic.Name binder, source)
414 | ["id", id; "sort", _] -> Def (id, Cic.Anonymous, source)
415 | _ -> attribute_error ())
416 | "arity" (* transparent elements (i.e. which contain a CIC) *)
424 let term = pop_cic ctxt in
425 pop ctxt; (* pops start tag matching current end tag (e.g. <arity>) *)
426 push ctxt (Cic_term term)
427 | "substitution" -> (* optional transparent elements (i.e. which _may_
429 set_top ctxt (* replace <substitution> *)
430 (match ctxt.stack with
431 | Cic_term term :: tl ->
433 (Meta_subst (Some term))
434 | _ -> Meta_subst None)
436 let target = pop_cic ctxt in
437 let rec add_decl target = function
438 | Decl (id, binder, source) :: tl ->
439 add_decl (Cic.AProd (id, binder, source, target)) tl
444 let term = add_decl target ctxt.stack in
445 (match pop_tag_attrs ctxt with
448 | _ -> attribute_error ());
449 push ctxt (Cic_term term)
451 let target = pop_cic ctxt in
452 let rec add_decl target = function
453 | Decl (id, binder, source) :: tl ->
454 add_decl (Cic.ALambda (id, binder, source, target)) tl
459 let term = add_decl target ctxt.stack in
460 (match pop_tag_attrs ctxt with
463 | _ -> attribute_error ());
464 push ctxt (Cic_term term)
466 let target = pop_cic ctxt in
467 let rec add_def target = function
468 | Def (id, binder, source) :: tl ->
469 add_def (Cic.ALetIn (id, binder, source, target)) tl
474 let term = add_def target ctxt.stack in
475 (match pop_tag_attrs ctxt with
478 | _ -> attribute_error ());
479 push ctxt (Cic_term term)
481 let typ = pop_cic ctxt in
482 let term = pop_cic ctxt in
484 (match pop_tag_attrs ctxt with
486 | ["id", id; "sort", _] -> Cic.ACast (id, term, typ)
487 | _ -> attribute_error ()));
490 (match pop_tag_attrs ctxt with
491 | ["id", id] -> Cic.AImplicit (id, None)
492 | ["annotation", annotation; "id", id] ->
493 let implicit_annotation =
494 match annotation with
495 | "closed" -> `Closed
498 | _ -> parse_error "invalid value for \"annotation\" attribute"
500 Cic.AImplicit (id, Some implicit_annotation)
501 | _ -> attribute_error ()))
503 let meta_substs = pop_meta_substs ctxt in
505 (match pop_tag_attrs ctxt with
506 | ["id", id; "no", no]
507 | ["id", id; "no", no; "sort", _] ->
508 Cic.AMeta (id, int_of_string no, meta_substs)
509 | _ -> attribute_error ()));
512 (match pop_tag_attrs ctxt with
513 | ["id", id; "noType", noType; "uri", uri] ->
514 Cic.AMutInd (id, uri_of_string uri, int_of_string noType, [])
515 | _ -> attribute_error ()));
518 (match pop_tag_attrs ctxt with
519 | ["id", id; "noConstr", noConstr; "noType", noType; "uri", uri]
520 | ["id", id; "noConstr", noConstr; "noType", noType; "sort", _;
522 Cic.AMutConstruct (id, uri_of_string uri, int_of_string noType,
523 int_of_string noConstr, [])
524 | _ -> attribute_error ()));
526 let body = pop_cic ctxt in
527 let typ = pop_cic ctxt in
529 (match pop_tag_attrs ctxt with
530 | ["id", id; "name", name; "recIndex", recIndex] ->
531 Fix_fun (id, name, int_of_string recIndex, typ, body)
532 | _ -> attribute_error ())
534 let body = pop_cic ctxt in
535 let typ = pop_cic ctxt in
537 (match pop_tag_attrs ctxt with
538 | ["id", id; "name", name] ->
539 Cofix_fun (id, name, typ, body)
540 | _ -> attribute_error ())
542 let fix_funs = pop_fix_funs ctxt in
544 (match pop_tag_attrs ctxt with
545 | ["id", id; "noFun", noFun]
546 | ["id", id; "noFun", noFun; "sort", _] ->
547 Cic.AFix (id, int_of_string noFun, fix_funs)
548 | _ -> attribute_error ()))
550 let cofix_funs = pop_cofix_funs ctxt in
552 (match pop_tag_attrs ctxt with
553 | ["id", id; "noFun", noFun]
554 | ["id", id; "noFun", noFun; "sort", _] ->
555 Cic.ACoFix (id, int_of_string noFun, cofix_funs)
556 | _ -> attribute_error ()))
558 (match pop_cics ctxt with
559 | patternsType :: inductiveTerm :: patterns ->
561 (match pop_tag_attrs ctxt with
562 | ["id", id; "noType", noType; "uriType", uriType]
563 | ["id", id; "noType", noType; "sort", _; "uriType", uriType] ->
564 Cic.AMutCase (id, uri_of_string uriType, int_of_string noType,
565 patternsType, inductiveTerm, patterns)
566 | _ -> attribute_error ()))
567 | _ -> parse_error "invalid \"MUTCASE\" content")
569 let typ = pop_cic ctxt in
571 (match pop_tag_attrs ctxt with
572 | ["name", name] -> Constructor (name, typ)
573 | _ -> attribute_error ())
575 let constructors = pop_constructors ctxt in
576 let arity = pop_cic ctxt in
578 (match pop_tag_attrs ctxt with
579 | ["id", id; "inductive", inductive; "name", name] ->
580 Inductive_type (id, name, bool_of_string inductive, arity,
582 | _ -> attribute_error ())
583 | "InductiveDefinition" ->
584 let inductive_types = pop_inductive_types ctxt in
585 let obj_attributes = pop_obj_attributes ctxt in
587 (match pop_tag_attrs ctxt with
588 | ["id", id; "noParams", noParams; "params", params] ->
589 Cic.AInductiveDefinition (id, inductive_types,
590 uri_list_of_string params, int_of_string noParams, obj_attributes)
591 | _ -> attribute_error ()))
593 let typ = pop_cic ctxt in
594 let obj_attributes = pop_obj_attributes ctxt in
596 (match pop_tag_attrs ctxt with
597 | ["id", id; "name", name; "params", params] ->
598 Cic_constant_type (id, name, uri_list_of_string params, typ,
600 | _ -> attribute_error ())
602 let body = pop_cic ctxt in
603 let obj_attributes = pop_obj_attributes ctxt in
605 (match pop_tag_attrs ctxt with
606 | ["for", for_; "id", id; "params", params] ->
607 Cic_constant_body (id, for_, uri_list_of_string params, body,
609 | _ -> attribute_error ())
611 let typ = pop_cic ctxt in
613 match pop_cics ctxt with
616 | _ -> parse_error "wrong content for \"Variable\""
618 let obj_attributes = pop_obj_attributes ctxt in
620 (match pop_tag_attrs ctxt with
621 | ["id", id; "name", name; "params", params] ->
622 Cic.AVariable (id, name, body, typ, uri_list_of_string params,
624 | _ -> attribute_error ()))
626 let term = pop_cic ctxt in
628 (match pop_tag_attrs ctxt with
629 | ["relUri", relUri] -> Arg (relUri, term)
630 | _ -> attribute_error ())
632 (* explicit named substitution handling: when the end tag of an element
633 * subject of exlicit named subst (MUTIND, MUTCONSTRUCT, CONST, VAR) it
634 * is stored on the stack with no substitutions (i.e. []). When the end
635 * tag of an "instantiate" element is found we patch the term currently
636 * on the stack with the substitution built from "instantiate" children
638 (* XXX inefficiency here: first travels the <arg> elements in order to
639 * find the baseUri, then in order to build the explicit named subst *)
640 let base_uri = find_base_uri ctxt in
641 let subst = pop_subst ctxt base_uri in
642 let term = pop_cic ctxt in
643 (* comment from CicParser3.ml:
644 * CSC: the "id" optional attribute should be parsed and reflected in
645 * Cic.annterm and id = string_of_xml_attr (n#attribute "id") *)
646 (* replace <instantiate> *)
647 set_top ctxt (Cic_term (patch_subst ctxt subst term))
649 let rec aux acc = function (* retrieve object attributes *)
650 | Obj_class c :: tl -> aux (`Class c :: acc) tl
651 | Obj_flavour f :: tl -> aux (`Flavour f :: acc) tl
652 | Obj_generated :: tl -> aux (`Generated :: acc) tl
655 let obj_attrs, new_stack = aux [] ctxt.stack in
656 ctxt.stack <- new_stack;
657 set_top ctxt (Cic_attributes obj_attrs)
658 | "generated" -> set_top ctxt Obj_generated
661 (match pop_tag_attrs ctxt with
662 | ["name", name] -> Obj_field name
663 | _ -> attribute_error ())
666 (match pop_tag_attrs ctxt with
667 | [ "value", "definition"] -> Obj_flavour `Definition
668 | [ "value", "fact"] -> Obj_flavour `Fact
669 | [ "value", "lemma"] -> Obj_flavour `Lemma
670 | [ "value", "remark"] -> Obj_flavour `Remark
671 | [ "value", "theorem"] -> Obj_flavour `Theorem
672 | [ "value", "variant"] -> Obj_flavour `Variant
673 | _ -> attribute_error ())
675 let class_modifiers = pop_class_modifiers ctxt in
677 (match pop_tag_attrs ctxt with
678 | ["value", "coercion"] -> Obj_class `Coercion
679 | ["value", "elim"] ->
680 (match class_modifiers with
681 | [Cic_term (Cic.ASort (_, sort))] -> Obj_class (`Elim sort)
684 "unexpected extra content for \"elim\" object class")
685 | ["value", "record"] ->
690 (match Str.split (Str.regexp " ") name with
691 | [name] -> name, false
692 | [name;"coercion"] -> name,true
695 "wrong \"field\"'s name attribute")
698 "unexpected extra content for \"record\" object class")
701 Obj_class (`Record fields)
702 | ["value", "projection"] -> Obj_class `Projection
703 | _ -> attribute_error ())
705 match find_helm_exception ctxt with
706 | Some (exn, arg) -> raise (Getter_failure (exn, arg))
707 | None -> parse_error (sprintf "unknown element \"%s\"" tag)
709 (** {2 Parser internals} *)
711 let has_gz_suffix fname =
713 let idx = String.rindex fname '.' in
714 let suffix = String.sub fname idx (String.length fname - idx) in
716 with Not_found -> false
718 let parse uri filename =
719 let ctxt = new_parser_context uri in
720 ctxt.filename <- filename;
721 let module P = XmlPushParser in
723 P.default_callbacks with
724 P.start_element = Some (start_element ctxt);
725 P.end_element = Some (end_element ctxt);
727 let xml_parser = P.create_parser callbacks in
728 ctxt.xml_parser <- Some xml_parser;
732 if has_gz_suffix filename then `Gzip_file filename
735 P.parse xml_parser xml_source
737 ctxt.xml_parser <- None;
738 (* ZACK: the above "<- None" is vital for garbage collection. Without it
739 * we keep in memory a circular structure parser -> callbacks -> ctxt ->
740 * parser. I don't know if the ocaml garbage collector is supposed to
741 * collect such structures, but for sure the expat bindings will (orribly)
742 * leak when used in conjunction with such structures *)
744 ctxt.xml_parser <- None; (* ZACK: same comment as above *)
745 (* debug_print (lazy (string_of_stack stack));*)
746 (* assert (List.length ctxt.stack = 1) *)
749 | Failure "int_of_string" -> parse_error ctxt "integer number expected"
750 | Invalid_argument "bool_of_string" -> parse_error ctxt "boolean expected"
751 | P.Parse_error msg -> parse_error ctxt ("parse error: " ^ msg)
753 | Getter_failure _ as exn ->
756 raise (Parser_failure ("uncaught exception: " ^ Printexc.to_string exn))
758 (** {2 API implementation} *)
760 let annobj_of_xml uri filename filenamebody =
761 match filenamebody with
763 (match parse uri filename with
764 | Cic_constant_type (id, name, params, typ, obj_attributes) ->
765 Cic.AConstant (id, None, name, None, typ, params, obj_attributes)
767 | _ -> raise (Parser_failure ("no object found in " ^ filename)))
768 | Some filenamebody ->
769 (match parse uri filename, parse uri filenamebody with
770 | Cic_constant_type (type_id, name, params, typ, obj_attributes),
771 Cic_constant_body (body_id, _, _, body, _) ->
772 Cic.AConstant (type_id, Some body_id, name, Some body, typ, params,[])
774 raise (Parser_failure (sprintf "no constant found in %s, %s"
775 filename filenamebody)))
777 let obj_of_xml uri filename filenamebody =
778 Deannotate.deannotate_obj (annobj_of_xml uri filename filenamebody)