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/
29 let debug_print s = if debug then prerr_endline (Lazy.force s)
33 (* ZACK TODO element from the DTD still to be handled:
34 <!ELEMENT CurrentProof (Conjecture*,body)>
35 <!ELEMENT Sequent %sequent;>
36 <!ELEMENT Conjecture %sequent;>
37 <!ELEMENT Decl %term;>
39 <!ELEMENT Hidden EMPTY>
40 <!ELEMENT Goal %term;>
43 exception Getter_failure of string * string
44 exception Parser_failure of string
47 | Arg of string * Cic.annterm (* relative uri, term *)
48 (* constants' body and types resides in differne files, thus we can't simple
49 * keep constants in Cic_obj stack entries *)
50 | Cic_attributes of Cic.attribute list
51 | Cic_constant_body of string * string * UriManager.uri list * Cic.annterm
53 (* id, for, params, body, object attributes *)
54 | Cic_constant_type of string * string * UriManager.uri list * Cic.annterm
56 (* id, name, params, type, object attributes *)
57 | Cic_term of Cic.annterm (* term *)
58 | Cic_obj of Cic.annobj (* object *)
59 | Cofix_fun of Cic.id * string * Cic.annterm * Cic.annterm
60 (* id, name, type, body *)
61 | Constructor of string * Cic.annterm (* name, type *)
62 | Decl of Cic.id * Cic.name * Cic.annterm (* id, binder, source *)
63 | Def of Cic.id * Cic.name * Cic.annterm * Cic.annterm (* id, binder, source, type *)
64 | Fix_fun of Cic.id * string * int * Cic.annterm * Cic.annterm
65 (* id, name, ind. index, type, body *)
66 | Inductive_type of string * string * bool * Cic.annterm *
67 (string * Cic.annterm) list (* id, name, inductive, arity, constructors *)
68 | Meta_subst of Cic.annterm option
69 | Obj_class of Cic.object_class
70 | Obj_flavour of Cic.object_flavour
71 | Obj_field of string (* field name *)
73 | Tag of string * (string * string) list (* tag name, attributes *)
74 (* ZACK TODO add file position to tag stack entry so that when attribute
75 * errors occur, the position of their _start_tag_ could be printed
76 * instead of the current position (usually the end tag) *)
79 mutable stack: stack_entry list;
80 mutable xml_parser: XmlPushParser.xml_parser option;
81 mutable filename: string;
85 let string_of_stack ctxt =
86 "[" ^ (String.concat "; "
89 | Arg (reluri, _) -> sprintf "Arg %s" reluri
90 | Cic_attributes _ -> "Cic_attributes"
91 | Cic_constant_body (id, name, _, _, _) ->
92 sprintf "Cic_constant_body %s (id=%s)" name id
93 | Cic_constant_type (id, name, _, _, _) ->
94 sprintf "Cic_constant_type %s (id=%s)" name id
95 | Cic_term _ -> "Cic_term"
96 | Cic_obj _ -> "Cic_obj"
97 | Constructor (name, _) -> "Constructor " ^ name
98 | Cofix_fun (id, _, _, _) -> sprintf "Cofix_fun (id=%s)" id
99 | Decl (id, _, _) -> sprintf "Decl (id=%s)" id
100 | Def (id, _, _, _) -> sprintf "Def (id=%s)" id
101 | Fix_fun (id, _, _, _, _) -> sprintf "Fix_fun (id=%s)" id
102 | Inductive_type (id, name, _, _, _) ->
103 sprintf "Inductive_type %s (id=%s)" name id
104 | Meta_subst _ -> "Meta_subst"
105 | Obj_class _ -> "Obj_class"
106 | Obj_flavour _ -> "Obj_flavour"
107 | Obj_field name -> "Obj_field " ^ name
108 | Obj_generated -> "Obj_generated"
109 | Tag (tag, _) -> "Tag " ^ tag)
112 let compare_attrs (a1, v1) (a2, v2) = Pervasives.compare a1 a2
113 let sort_attrs = List.sort compare_attrs
115 let new_parser_context uri = {
122 let get_parser ctxt =
123 match ctxt.xml_parser with
125 | None -> assert false
127 (** {2 Error handling} *)
129 let parse_error ctxt msg =
130 let (line, col) = XmlPushParser.get_position (get_parser ctxt) in
131 raise (Parser_failure (sprintf "[%s: line %d, column %d] %s"
132 ctxt.filename line col msg))
134 let attribute_error ctxt tag =
135 parse_error ctxt ("wrong attribute set for " ^ tag)
137 (** {2 Parsing context management} *)
140 (* debug_print (lazy "pop");*)
141 match ctxt.stack with
142 | hd :: tl -> (ctxt.stack <- tl)
146 (* debug_print (lazy "push");*)
147 ctxt.stack <- v :: ctxt.stack
150 (* debug_print (lazy "set_top");*)
151 match ctxt.stack with
152 | _ :: tl -> (ctxt.stack <- v :: tl)
155 (** pop the last tag from the open tags stack returning a pair <tag_name,
158 match ctxt.stack with
159 | Tag (tag, attrs) :: tl ->
162 | _ -> parse_error ctxt "unexpected extra content"
164 (** pop the last tag from the open tags stack returning its attributes.
165 * Attributes are returned as a list of pair <name, value> _sorted_ by
167 let pop_tag_attrs ctxt = sort_attrs (snd (pop_tag ctxt))
170 let rec aux acc stack =
172 | Cic_term t :: tl -> aux (t :: acc) tl
175 let values, new_stack = aux [] ctxt.stack in
176 ctxt.stack <- new_stack;
179 let pop_class_modifiers ctxt =
180 let rec aux acc stack =
182 | (Cic_term (Cic.ASort _) as m) :: tl
183 | (Obj_field _ as m) :: tl ->
187 let values, new_stack = aux [] ctxt.stack in
188 ctxt.stack <- new_stack;
191 let pop_meta_substs ctxt =
192 let rec aux acc stack =
194 | Meta_subst t :: tl -> aux (t :: acc) tl
197 let values, new_stack = aux [] ctxt.stack in
198 ctxt.stack <- new_stack;
201 let pop_fix_funs ctxt =
202 let rec aux acc stack =
204 | Fix_fun (id, name, index, typ, body) :: tl ->
205 aux ((id, name, index, typ, body) :: acc) tl
208 let values, new_stack = aux [] ctxt.stack in
209 ctxt.stack <- new_stack;
212 let pop_cofix_funs ctxt =
213 let rec aux acc stack =
215 | Cofix_fun (id, name, typ, body) :: tl ->
216 aux ((id, name, typ, body) :: acc) tl
219 let values, new_stack = aux [] ctxt.stack in
220 ctxt.stack <- new_stack;
223 let pop_constructors ctxt =
224 let rec aux acc stack =
226 | Constructor (name, t) :: tl -> aux ((name, t) :: acc) tl
229 let values, new_stack = aux [] ctxt.stack in
230 ctxt.stack <- new_stack;
233 let pop_inductive_types ctxt =
234 let rec aux acc stack =
236 | Inductive_type (id, name, ind, arity, ctors) :: tl ->
237 aux ((id, name, ind, arity, ctors) :: acc) tl
240 let values, new_stack = aux [] ctxt.stack in
242 parse_error ctxt "no \"InductiveType\" element found";
243 ctxt.stack <- new_stack;
246 (** travels the stack (without popping) for the first term subject of explicit
247 * named substitution and return its URI *)
248 let find_base_uri ctxt =
249 let rec aux = function
250 | Cic_term (Cic.AConst (_, uri, _)) :: _
251 | Cic_term (Cic.AMutInd (_, uri, _, _)) :: _
252 | Cic_term (Cic.AMutConstruct (_, uri, _, _, _)) :: _
253 | Cic_term (Cic.AVar (_, uri, _)) :: _ ->
255 | Arg _ :: tl -> aux tl
256 | _ -> parse_error ctxt "no \"arg\" element found"
258 UriManager.buri_of_uri (aux ctxt.stack)
260 (** backwardly eats the stack building an explicit named substitution from Arg
262 let pop_subst ctxt base_uri =
263 let rec aux acc stack =
265 | Arg (rel_uri, term) :: tl ->
266 let uri = UriManager.uri_of_string (base_uri ^ "/" ^ rel_uri) in
267 aux ((uri, term) :: acc) tl
270 let subst, new_stack = aux [] ctxt.stack in
272 parse_error ctxt "no \"arg\" element found";
273 ctxt.stack <- new_stack;
277 match ctxt.stack with
278 | Cic_term t :: tl ->
281 | _ -> parse_error ctxt "no cic term found"
283 let pop_obj_attributes ctxt =
284 match ctxt.stack with
285 | Cic_attributes attributes :: tl ->
290 (** {2 Auxiliary functions} *)
292 let uri_of_string = UriManager.uri_of_string
294 let uri_list_of_string =
295 let space_RE = Str.regexp " " in
297 List.map uri_of_string (Str.split space_RE s)
299 let impredicative_set = ref true;;
301 let sort_of_string ctxt = function
303 (* THIS CASE IS HERE ONLY TO ALLOW THE PARSING OF COQ LIBRARY
304 * THIS SHOULD BE REMOVED AS SOON AS univ_maker OR COQ'S EXPORTATION
306 | "CProp" -> Cic.CProp (CicUniv.fresh ~uri:ctxt.uri ())
307 | "Type" -> Cic.Type (CicUniv.fresh ~uri:ctxt.uri ())
308 | "Set" when !impredicative_set -> Cic.Set
309 | "Set" -> Cic.Type (CicUniv.fresh ~uri:ctxt.uri ())
311 let len = String.length s in
312 let sort_len, mk_sort =
313 if len > 5 && String.sub s 0 5 = "Type:" then 5,fun x -> Cic.Type x
314 else if len > 6 && String.sub s 0 6 = "CProp:" then 6,fun x->Cic.CProp x
315 else parse_error ctxt "sort expected"
317 let s = String.sub s sort_len (len - sort_len) in
318 let i = String.index s ':' in
319 let id = int_of_string (String.sub s 0 i) in
320 let suri = String.sub s (i+1) (len - sort_len - i - 1) in
321 let uri = UriManager.uri_of_string suri in
322 try mk_sort (CicUniv.fresh ~uri ~id ())
324 | Failure "int_of_string"
325 | Invalid_argument _ -> parse_error ctxt "sort expected"
327 let patch_subst ctxt subst = function
328 | Cic.AConst (id, uri, _) -> Cic.AConst (id, uri, subst)
329 | Cic.AMutInd (id, uri, typeno, _) ->
330 Cic.AMutInd (id, uri, typeno, subst)
331 | Cic.AMutConstruct (id, uri, typeno, consno, _) ->
332 Cic.AMutConstruct (id, uri, typeno, consno, subst)
333 | Cic.AVar (id, uri, _) -> Cic.AVar (id, uri, subst)
336 ("only \"CONST\", \"VAR\", \"MUTIND\", and \"MUTCONSTRUCT\" can be" ^
339 (** backwardly eats the stack seeking for the first open tag carrying
340 * "helm:exception" attributes. If found return Some of a pair containing
341 * exception name and argument. Return None otherwise *)
342 let find_helm_exception ctxt =
343 let rec aux = function
345 | Tag (_, attrs) :: tl ->
347 let exn = List.assoc "helm:exception" attrs in
349 try List.assoc "helm:exception_arg" attrs with Not_found -> ""
352 with Not_found -> aux tl)
357 (** {2 Push parser callbacks}
358 * each callback needs to be instantiated to a parsing context *)
360 let start_element ctxt tag attrs =
361 (* debug_print (lazy (sprintf "<%s%s>" tag (match attrs with | [] -> "" | _ -> " " ^ String.concat " " (List.map (fun (a,v) -> sprintf "%s=\"%s\"" a v) attrs))));*)
362 push ctxt (Tag (tag, attrs))
364 let end_element ctxt tag =
365 (* debug_print (lazy (sprintf "</%s>" tag));*)
366 (* debug_print (lazy (string_of_stack ctxt));*)
367 let attribute_error () = attribute_error ctxt tag in
368 let parse_error = parse_error ctxt in
369 let sort_of_string = sort_of_string ctxt in
373 (match pop_tag_attrs ctxt with
374 | ["binder", binder; "id", id; "idref", idref; "value", value]
375 | ["binder", binder; "id", id; "idref", idref; "sort", _;
377 Cic.ARel (id, idref, int_of_string value, binder)
378 | _ -> attribute_error ()))
381 (match pop_tag_attrs ctxt with
382 | ["id", id; "uri", uri]
383 | ["id", id; "sort", _; "uri", uri] ->
384 Cic.AVar (id, uri_of_string uri, [])
385 | _ -> attribute_error ()))
388 (match pop_tag_attrs ctxt with
389 | ["id", id; "uri", uri]
390 | ["id", id; "sort", _; "uri", uri] ->
391 Cic.AConst (id, uri_of_string uri, [])
392 | _ -> attribute_error ()))
395 (match pop_tag_attrs ctxt with
396 | ["id", id; "value", sort] -> Cic.ASort (id, sort_of_string sort)
397 | _ -> attribute_error ()))
399 let args = pop_cics ctxt in
401 (match pop_tag_attrs ctxt with
403 | ["id", id; "sort", _] -> Cic.AAppl (id, args)
404 | _ -> attribute_error ()))
406 let source = pop_cic ctxt in
408 (match pop_tag_attrs ctxt with
409 | ["binder", binder; "id", id ]
410 | ["binder", binder; "id", id; "type", _] ->
411 Decl (id, Cic.Name binder, source)
413 | ["id", id; "type", _] -> Decl (id, Cic.Anonymous, source)
414 | _ -> attribute_error ())
415 | "def" -> (* same as "decl" above *)
417 (*CSC: hack to parse Coq files where the LetIn is not typed *)
418 let ty = pop_cic ctxt in
420 let source = pop_cic ctxt in
423 Parser_failure _ -> Cic.AImplicit ("MISSING_def_TYPE",None),ty
426 (match pop_tag_attrs ctxt with
427 | ["binder", binder; "id", id]
428 | ["binder", binder; "id", id; "sort", _] ->
429 Def (id, Cic.Name binder, source, ty)
431 | ["id", id; "sort", _] -> Def (id, Cic.Anonymous, source, ty)
432 | _ -> attribute_error ())
433 | "arity" (* transparent elements (i.e. which contain a CIC) *)
441 let term = pop_cic ctxt in
442 pop ctxt; (* pops start tag matching current end tag (e.g. <arity>) *)
443 push ctxt (Cic_term term)
444 | "substitution" -> (* optional transparent elements (i.e. which _may_
446 set_top ctxt (* replace <substitution> *)
447 (match ctxt.stack with
448 | Cic_term term :: tl ->
450 (Meta_subst (Some term))
451 | _ -> Meta_subst None)
453 let target = pop_cic ctxt in
454 let rec add_decl target = function
455 | Decl (id, binder, source) :: tl ->
456 add_decl (Cic.AProd (id, binder, source, target)) tl
461 let term = add_decl target ctxt.stack in
462 (match pop_tag_attrs ctxt with
465 | _ -> attribute_error ());
466 push ctxt (Cic_term term)
468 let target = pop_cic ctxt in
469 let rec add_decl target = function
470 | Decl (id, binder, source) :: tl ->
471 add_decl (Cic.ALambda (id, binder, source, target)) tl
476 let term = add_decl target ctxt.stack in
477 (match pop_tag_attrs ctxt with
480 | _ -> attribute_error ());
481 push ctxt (Cic_term term)
483 let target = pop_cic ctxt in
484 let rec add_def target = function
485 | Def (id, binder, source, ty) :: tl ->
486 add_def (Cic.ALetIn (id, binder, source, ty, target)) tl
491 let term = add_def target ctxt.stack in
492 (match pop_tag_attrs ctxt with
495 | _ -> attribute_error ());
496 push ctxt (Cic_term term)
498 let typ = pop_cic ctxt in
499 let term = pop_cic ctxt in
501 (match pop_tag_attrs ctxt with
503 | ["id", id; "sort", _] -> Cic.ACast (id, term, typ)
504 | _ -> attribute_error ()));
507 (match pop_tag_attrs ctxt with
508 | ["id", id] -> Cic.AImplicit (id, None)
509 | ["annotation", annotation; "id", id] ->
510 let implicit_annotation =
511 match annotation with
512 | "closed" -> `Closed
515 | _ -> parse_error "invalid value for \"annotation\" attribute"
517 Cic.AImplicit (id, Some implicit_annotation)
518 | _ -> attribute_error ()))
520 let meta_substs = pop_meta_substs ctxt in
522 (match pop_tag_attrs ctxt with
523 | ["id", id; "no", no]
524 | ["id", id; "no", no; "sort", _] ->
525 Cic.AMeta (id, int_of_string no, meta_substs)
526 | _ -> attribute_error ()));
529 (match pop_tag_attrs ctxt with
530 | ["id", id; "noType", noType; "uri", uri] ->
531 Cic.AMutInd (id, uri_of_string uri, int_of_string noType, [])
532 | _ -> attribute_error ()));
535 (match pop_tag_attrs ctxt with
536 | ["id", id; "noConstr", noConstr; "noType", noType; "uri", uri]
537 | ["id", id; "noConstr", noConstr; "noType", noType; "sort", _;
539 Cic.AMutConstruct (id, uri_of_string uri, int_of_string noType,
540 int_of_string noConstr, [])
541 | _ -> attribute_error ()));
543 let body = pop_cic ctxt in
544 let typ = pop_cic ctxt in
546 (match pop_tag_attrs ctxt with
547 | ["id", id; "name", name; "recIndex", recIndex] ->
548 Fix_fun (id, name, int_of_string recIndex, typ, body)
549 | _ -> attribute_error ())
551 let body = pop_cic ctxt in
552 let typ = pop_cic ctxt in
554 (match pop_tag_attrs ctxt with
555 | ["id", id; "name", name] ->
556 Cofix_fun (id, name, typ, body)
557 | _ -> attribute_error ())
559 let fix_funs = pop_fix_funs ctxt in
561 (match pop_tag_attrs ctxt with
562 | ["id", id; "noFun", noFun]
563 | ["id", id; "noFun", noFun; "sort", _] ->
564 Cic.AFix (id, int_of_string noFun, fix_funs)
565 | _ -> attribute_error ()))
567 let cofix_funs = pop_cofix_funs ctxt in
569 (match pop_tag_attrs ctxt with
570 | ["id", id; "noFun", noFun]
571 | ["id", id; "noFun", noFun; "sort", _] ->
572 Cic.ACoFix (id, int_of_string noFun, cofix_funs)
573 | _ -> attribute_error ()))
575 (match pop_cics ctxt with
576 | patternsType :: inductiveTerm :: patterns ->
578 (match pop_tag_attrs ctxt with
579 | ["id", id; "noType", noType; "uriType", uriType]
580 | ["id", id; "noType", noType; "sort", _; "uriType", uriType] ->
581 Cic.AMutCase (id, uri_of_string uriType, int_of_string noType,
582 patternsType, inductiveTerm, patterns)
583 | _ -> attribute_error ()))
584 | _ -> parse_error "invalid \"MUTCASE\" content")
586 let typ = pop_cic ctxt in
588 (match pop_tag_attrs ctxt with
589 | ["name", name] -> Constructor (name, typ)
590 | _ -> attribute_error ())
592 let constructors = pop_constructors ctxt in
593 let arity = pop_cic ctxt in
595 (match pop_tag_attrs ctxt with
596 | ["id", id; "inductive", inductive; "name", name] ->
597 Inductive_type (id, name, bool_of_string inductive, arity,
599 | _ -> attribute_error ())
600 | "InductiveDefinition" ->
601 let inductive_types = pop_inductive_types ctxt in
602 let obj_attributes = pop_obj_attributes ctxt in
604 (match pop_tag_attrs ctxt with
605 | ["id", id; "noParams", noParams; "params", params] ->
606 Cic.AInductiveDefinition (id, inductive_types,
607 uri_list_of_string params, int_of_string noParams, obj_attributes)
608 | _ -> attribute_error ()))
610 let typ = pop_cic ctxt in
611 let obj_attributes = pop_obj_attributes ctxt in
613 (match pop_tag_attrs ctxt with
614 | ["id", id; "name", name; "params", params] ->
615 Cic_constant_type (id, name, uri_list_of_string params, typ,
617 | _ -> attribute_error ())
619 let body = pop_cic ctxt in
620 let obj_attributes = pop_obj_attributes ctxt in
622 (match pop_tag_attrs ctxt with
623 | ["for", for_; "id", id; "params", params] ->
624 Cic_constant_body (id, for_, uri_list_of_string params, body,
626 | _ -> attribute_error ())
628 let typ = pop_cic ctxt in
630 match pop_cics ctxt with
633 | _ -> parse_error "wrong content for \"Variable\""
635 let obj_attributes = pop_obj_attributes ctxt in
637 (match pop_tag_attrs ctxt with
638 | ["id", id; "name", name; "params", params] ->
639 Cic.AVariable (id, name, body, typ, uri_list_of_string params,
641 | _ -> attribute_error ()))
643 let term = pop_cic ctxt in
645 (match pop_tag_attrs ctxt with
646 | ["relUri", relUri] -> Arg (relUri, term)
647 | _ -> attribute_error ())
649 (* explicit named substitution handling: when the end tag of an element
650 * subject of exlicit named subst (MUTIND, MUTCONSTRUCT, CONST, VAR) it
651 * is stored on the stack with no substitutions (i.e. []). When the end
652 * tag of an "instantiate" element is found we patch the term currently
653 * on the stack with the substitution built from "instantiate" children
655 (* XXX inefficiency here: first travels the <arg> elements in order to
656 * find the baseUri, then in order to build the explicit named subst *)
657 let base_uri = find_base_uri ctxt in
658 let subst = pop_subst ctxt base_uri in
659 let term = pop_cic ctxt in
660 (* comment from CicParser3.ml:
661 * CSC: the "id" optional attribute should be parsed and reflected in
662 * Cic.annterm and id = string_of_xml_attr (n#attribute "id") *)
663 (* replace <instantiate> *)
664 set_top ctxt (Cic_term (patch_subst ctxt subst term))
666 let rec aux acc = function (* retrieve object attributes *)
667 | Obj_class c :: tl -> aux (`Class c :: acc) tl
668 | Obj_flavour f :: tl -> aux (`Flavour f :: acc) tl
669 | Obj_generated :: tl -> aux (`Generated :: acc) tl
672 let obj_attrs, new_stack = aux [] ctxt.stack in
673 ctxt.stack <- new_stack;
674 set_top ctxt (Cic_attributes obj_attrs)
675 | "generated" -> set_top ctxt Obj_generated
678 (match pop_tag_attrs ctxt with
679 | ["name", name] -> Obj_field name
680 | _ -> attribute_error ())
683 (match pop_tag_attrs ctxt with
684 | [ "value", "definition"] -> Obj_flavour `Definition
685 | [ "value", "mutual_definition"] -> Obj_flavour `MutualDefinition
686 | [ "value", "fact"] -> Obj_flavour `Fact
687 | [ "value", "lemma"] -> Obj_flavour `Lemma
688 | [ "value", "remark"] -> Obj_flavour `Remark
689 | [ "value", "theorem"] -> Obj_flavour `Theorem
690 | [ "value", "variant"] -> Obj_flavour `Variant
691 | [ "value", "axiom"] -> Obj_flavour `Axiom
692 | _ -> attribute_error ())
694 let class_modifiers = pop_class_modifiers ctxt in
696 (match pop_tag_attrs ctxt with
697 | ["value", "elim"] ->
698 (match class_modifiers with
699 | [Cic_term (Cic.ASort (_, sort))] -> Obj_class (`Elim sort)
702 "unexpected extra content for \"elim\" object class")
703 | ["value", "record"] ->
708 (match Str.split (Str.regexp " ") name with
709 | [name] -> name, false, 0
710 | [name;"coercion"] -> name,true,0
711 | [name;"coercion"; n] ->
715 parse_error "int expected after \"coercion\""
720 "wrong \"field\"'s name attribute")
723 "unexpected extra content for \"record\" object class")
726 Obj_class (`Record fields)
727 | ["value", "projection"] -> Obj_class `Projection
728 | ["value", "inversion"] -> Obj_class `InversionPrinciple
729 | _ -> attribute_error ())
731 match find_helm_exception ctxt with
732 | Some (exn, arg) -> raise (Getter_failure (exn, arg))
733 | None -> parse_error (sprintf "unknown element \"%s\"" tag)
735 (** {2 Parser internals} *)
737 let has_gz_suffix fname =
739 let idx = String.rindex fname '.' in
740 let suffix = String.sub fname idx (String.length fname - idx) in
742 with Not_found -> false
744 let parse uri filename =
745 let ctxt = new_parser_context uri in
746 ctxt.filename <- filename;
747 let module P = XmlPushParser in
749 P.default_callbacks with
750 P.start_element = Some (start_element ctxt);
751 P.end_element = Some (end_element ctxt);
753 let xml_parser = P.create_parser callbacks in
754 ctxt.xml_parser <- Some xml_parser;
758 if has_gz_suffix filename then `Gzip_file filename
761 P.parse xml_parser xml_source
763 ctxt.xml_parser <- None;
764 (* ZACK: the above "<- None" is vital for garbage collection. Without it
765 * we keep in memory a circular structure parser -> callbacks -> ctxt ->
766 * parser. I don't know if the ocaml garbage collector is supposed to
767 * collect such structures, but for sure the expat bindings will (orribly)
768 * leak when used in conjunction with such structures *)
770 ctxt.xml_parser <- None; (* ZACK: same comment as above *)
771 (* debug_print (lazy (string_of_stack stack));*)
772 (* assert (List.length ctxt.stack = 1) *)
775 | Failure "int_of_string" -> parse_error ctxt "integer number expected"
776 | Invalid_argument "bool_of_string" -> parse_error ctxt "boolean expected"
777 | P.Parse_error msg -> parse_error ctxt ("parse error: " ^ msg)
780 | Getter_failure _ as exn ->
783 raise (Parser_failure ("CicParser: uncaught exception: " ^ Printexc.to_string exn))
785 (** {2 API implementation} *)
787 let annobj_of_xml uri filename filenamebody =
788 match filenamebody with
790 (match parse uri filename with
791 | Cic_constant_type (id, name, params, typ, obj_attributes) ->
792 Cic.AConstant (id, None, name, None, typ, params, obj_attributes)
794 | _ -> raise (Parser_failure ("no object found in " ^ filename)))
795 | Some filenamebody ->
796 (match parse uri filename, parse uri filenamebody with
797 | Cic_constant_type (type_id, name, params, typ, obj_attributes),
798 Cic_constant_body (body_id, _, _, body, _) ->
799 Cic.AConstant (type_id, Some body_id, name, Some body, typ, params,obj_attributes)
801 raise (Parser_failure (sprintf "no constant found in %s, %s"
802 filename filenamebody)))
804 let obj_of_xml uri filename filenamebody =
805 Deannotate.deannotate_obj (annobj_of_xml uri filename filenamebody)