]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/grafite_parser/grafiteParser.ml
Added syntax for ninversion tactic (still experimental).
[helm.git] / helm / software / components / grafite_parser / grafiteParser.ml
1 (* Copyright (C) 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 (* $Id$ *)
27
28 module N  = CicNotationPt
29 module G  = GrafiteAst
30 module L  = LexiconAst
31 module LE = LexiconEngine
32
33 exception NoInclusionPerformed of string (* full path *)
34
35 type 'a localized_option =
36    LSome of 'a
37  | LNone of G.loc
38
39 type ast_statement =
40   (N.term, N.term, N.term G.reduction, N.term N.obj, string) G.statement
41
42 type 'status statement =
43   ?never_include:bool -> 
44     (* do not call LexiconEngine to do includes, always raise NoInclusionPerformed *) 
45   include_paths:string list -> (#LE.status as 'status) ->
46     'status * ast_statement localized_option
47
48 type 'status parser_status = {
49   grammar : Grammar.g;
50   term : N.term Grammar.Entry.e;
51   statement : #LE.status as 'status statement Grammar.Entry.e;
52 }
53
54 let grafite_callback = ref (fun _ -> ())
55 let set_grafite_callback cb = grafite_callback := cb
56
57 let lexicon_callback = ref (fun _ -> ())
58 let set_lexicon_callback cb = lexicon_callback := cb
59
60 let initial_parser () = 
61   let grammar = CicNotationParser.level2_ast_grammar () in
62   let term = CicNotationParser.term () in
63   let statement = Grammar.Entry.create grammar "statement" in
64   { grammar = grammar; term = term; statement = statement }
65 ;;
66
67 let grafite_parser = ref (initial_parser ())
68
69 let add_raw_attribute ~text t = N.AttributedTerm (`Raw text, t)
70
71 let default_associativity = Gramext.NonA
72         
73 let mk_rec_corec ind_kind defs loc = 
74  (* In case of mutual definitions here we produce just
75     the syntax tree for the first one. The others will be
76     generated from the completely specified term just before
77     insertion in the environment. We use the flavour
78     `MutualDefinition to rememer this. *)
79   let name,ty = 
80     match defs with
81     | (params,(N.Ident (name, None), ty),_,_) :: _ ->
82         let ty = match ty with Some ty -> ty | None -> N.Implicit `JustOne in
83         let ty =
84          List.fold_right
85           (fun var ty -> N.Binder (`Pi,var,ty)
86           ) params ty
87         in
88          name,ty
89     | _ -> assert false 
90   in
91   let body = N.Ident (name,None) in
92   let flavour =
93    if List.length defs = 1 then
94     `Definition
95    else
96     `MutualDefinition
97   in
98    (loc, N.Theorem(flavour, name, ty, Some (N.LetRec (ind_kind, defs, body)), `Regular))
99
100 let nmk_rec_corec ind_kind defs loc = 
101  let loc,t = mk_rec_corec ind_kind defs loc in
102   G.NObj (loc,t)
103
104 let mk_rec_corec ind_kind defs loc = 
105  let loc,t = mk_rec_corec ind_kind defs loc in
106   G.Obj (loc,t)
107
108 let npunct_of_punct = function
109   | G.Branch loc -> G.NBranch loc
110   | G.Shift loc -> G.NShift loc
111   | G.Pos (loc, i) -> G.NPos (loc, i)
112   | G.Wildcard loc -> G.NWildcard loc
113   | G.Merge loc -> G.NMerge loc
114   | G.Semicolon loc -> G.NSemicolon loc
115   | G.Dot loc -> G.NDot loc
116 ;;
117 let nnon_punct_of_punct = function
118   | G.Skip loc -> G.NSkip loc
119   | G.Unfocus loc -> G.NUnfocus loc
120   | G.Focus (loc,l) -> G.NFocus (loc,l)
121 ;;
122 let npunct_of_punct = function
123   | G.Branch loc -> G.NBranch loc
124   | G.Shift loc -> G.NShift loc
125   | G.Pos (loc, i) -> G.NPos (loc, i)
126   | G.Wildcard loc -> G.NWildcard loc
127   | G.Merge loc -> G.NMerge loc
128   | G.Semicolon loc -> G.NSemicolon loc
129   | G.Dot loc -> G.NDot loc
130 ;;
131
132 type by_continuation =
133    BYC_done
134  | BYC_weproved of N.term * string option * N.term option
135  | BYC_letsuchthat of string * N.term * string * N.term
136  | BYC_wehaveand of string * N.term * string * N.term
137
138 let initialize_parser () =
139   (* {{{ parser initialization *)
140   let term = !grafite_parser.term in
141   let statement = !grafite_parser.statement in
142   let let_defs = CicNotationParser.let_defs () in
143   let protected_binder_vars = CicNotationParser.protected_binder_vars () in
144 EXTEND
145   GLOBAL: term statement;
146   constructor: [ [ name = IDENT; SYMBOL ":"; typ = term -> (name, typ) ] ];
147   tactic_term: [ [ t = term LEVEL "90" -> t ] ];
148   new_name: [
149     [ SYMBOL "_" -> None
150     | id = IDENT -> Some id ]
151     ];
152   ident_list0: [ [ LPAREN; idents = LIST0 new_name; RPAREN -> idents ] ];
153   tactic_term_list1: [
154     [ tactic_terms = LIST1 tactic_term SEP SYMBOL "," -> tactic_terms ]
155   ];
156   reduction_kind: [
157     [ IDENT "normalize" -> `Normalize
158     | IDENT "simplify" -> `Simpl
159     | IDENT "unfold"; t = OPT tactic_term -> `Unfold t
160     | IDENT "whd" -> `Whd ]
161   ];
162   nreduction_kind: [
163     [ IDENT "nnormalize" ; delta = OPT [ IDENT "nodelta" -> () ] ->
164        let delta = match delta with None -> true | _ -> false in
165         `Normalize delta
166     (*| IDENT "unfold"; t = OPT tactic_term -> `Unfold t*)
167     | IDENT "nwhd" ; delta = OPT [ IDENT "nodelta" -> () ] ->
168        let delta = match delta with None -> true | _ -> false in
169         `Whd delta]
170   ];
171   sequent_pattern_spec: [
172    [ hyp_paths =
173       LIST0
174        [ id = IDENT ;
175          path = OPT [SYMBOL ":" ; path = tactic_term -> path ] ->
176          (id,match path with Some p -> p | None -> N.UserInput) ];
177      goal_path = OPT [ SYMBOL <:unicode<vdash>>; term = tactic_term -> term ] ->
178       let goal_path =
179        match goal_path, hyp_paths with
180           None, [] -> Some N.UserInput
181         | None, _::_ -> None
182         | Some goal_path, _ -> Some goal_path
183       in
184        hyp_paths,goal_path
185    ]
186   ];
187   pattern_spec: [
188     [ res = OPT [
189        "in";
190        wanted_and_sps =
191         [ "match" ; wanted = tactic_term ;
192           sps = OPT [ "in"; sps = sequent_pattern_spec -> sps ] ->
193            Some wanted,sps
194         | sps = sequent_pattern_spec ->
195            None,Some sps
196         ] ->
197          let wanted,hyp_paths,goal_path =
198           match wanted_and_sps with
199              wanted,None -> wanted, [], Some N.UserInput
200            | wanted,Some (hyp_paths,goal_path) -> wanted,hyp_paths,goal_path
201          in
202           wanted, hyp_paths, goal_path ] ->
203       match res with
204          None -> None,[],Some N.UserInput
205        | Some ps -> ps]
206   ];
207   inverter_param_list: [ 
208     [ params = tactic_term -> 
209       let deannotate = function
210         | N.AttributedTerm (_,t) | t -> t
211       in match deannotate params with
212       | N.Implicit _ -> [false]
213       | N.UserInput -> [true]
214       | N.Appl l -> 
215          List.map (fun x -> match deannotate x with  
216            | N.Implicit _ -> false
217            | N.UserInput -> true
218            | _ -> raise (Invalid_argument "malformed target parameter list 1")) l
219       | _ -> raise (Invalid_argument ("malformed target parameter list 2\n" ^ CicNotationPp.pp_term params)) ]
220   ];
221   direction: [
222     [ SYMBOL ">" -> `LeftToRight
223     | SYMBOL "<" -> `RightToLeft ]
224   ];
225   int: [ [ num = NUMBER -> int_of_string num ] ];
226   intros_names: [
227    [ idents = OPT ident_list0 ->
228       match idents with None -> [] | Some idents -> idents
229    ]
230   ];
231   intros_spec: [
232     [ OPT [ IDENT "names" ]; 
233       num = OPT [ num = int -> num ]; 
234       idents = intros_names ->
235         num, idents
236     ]
237   ];
238   using: [ [ using = OPT [ IDENT "using"; t = tactic_term -> t ] -> using ] ];
239   ntactic: [
240     [ IDENT "napply"; t = tactic_term -> G.NApply (loc, t)
241     | IDENT "napplyS"; t = tactic_term -> G.NSmartApply (loc, t)
242     | IDENT "nassert";
243        seqs = LIST0 [
244         hyps = LIST0
245          [ id = IDENT ; SYMBOL ":" ; ty = tactic_term -> id,`Decl ty
246          | id = IDENT ; SYMBOL ":" ; ty = tactic_term ;
247                         SYMBOL <:unicode<def>> ; bo = tactic_term ->
248             id,`Def (bo,ty)];
249         SYMBOL <:unicode<vdash>>;
250         concl = tactic_term -> (List.rev hyps,concl) ] ->
251          G.NAssert (loc, seqs)
252     | IDENT "nauto"; params = auto_params -> G.NAuto (loc, params)
253     | SYMBOL "/"; num = OPT NUMBER ; SYMBOL "/" ->
254         let depth = match num with Some n -> n | None -> "1" in
255         G.NAuto (loc, ([],["slir","";"depth",depth]))
256     | IDENT "ncases"; what = tactic_term ; where = pattern_spec ->
257         G.NCases (loc, what, where)
258     | IDENT "nchange"; what = pattern_spec; "with"; with_what = tactic_term -> 
259         G.NChange (loc, what, with_what)
260     | SYMBOL "@"; num = OPT NUMBER; l = LIST0 tactic_term -> 
261         G.NConstructor (loc,
262            (match num with None -> None | Some x -> Some (int_of_string x)),l)
263     | IDENT "ncut"; t = tactic_term -> G.NCut (loc, t)
264 (*  | IDENT "ndiscriminate"; t = tactic_term -> G.NDiscriminate (loc, t)
265     | IDENT "nsubst"; t = tactic_term -> G.NSubst (loc, t) *)
266     | IDENT "ndestruct" -> G.NDestruct loc
267     | IDENT "nelim"; what = tactic_term ; where = pattern_spec ->
268         G.NElim (loc, what, where)
269     | IDENT "ngeneralize"; p=pattern_spec ->
270         G.NGeneralize (loc, p)
271     | IDENT "ninversion"; what = tactic_term ; where = pattern_spec ->
272         G.NInversion (loc, what, where)
273     | IDENT "nlapply"; t = tactic_term -> G.NLApply (loc, t)
274     | IDENT "nletin"; name = IDENT ; SYMBOL <:unicode<def>> ; t = tactic_term;
275         where = pattern_spec ->
276         G.NLetIn (loc,where,t,name)
277     | kind = nreduction_kind; p = pattern_spec ->
278         G.NReduce (loc, kind, p)
279     | IDENT "nrewrite"; dir = direction; what = tactic_term ; where = pattern_spec ->   
280         G.NRewrite (loc, dir, what, where)
281     | IDENT "ntry"; tac = SELF -> G.NTry (loc,tac)
282     | IDENT "nrepeat"; tac = SELF -> G.NRepeat (loc,tac)
283     | LPAREN; l = LIST1 SELF; RPAREN -> G.NBlock (loc,l)
284     | IDENT "nassumption" -> G.NAssumption loc
285     | SYMBOL "#"; n=IDENT -> G.NIntro (loc,n)
286     | SYMBOL "#"; SYMBOL "_" -> G.NIntro (loc,"_")
287     | SYMBOL "*" -> G.NCase1 (loc,"_")
288     | SYMBOL "*"; n=IDENT ->
289         G.NCase1 (loc,n)
290     ]
291   ];
292   tactic: [
293     [ IDENT "absurd"; t = tactic_term ->
294         G.Absurd (loc, t)
295     | IDENT "apply"; IDENT "rule"; t = tactic_term ->
296         G.ApplyRule (loc, t)
297     | IDENT "apply"; t = tactic_term ->
298         G.Apply (loc, t)
299     | IDENT "applyP"; t = tactic_term ->
300         G.ApplyP (loc, t)
301     | IDENT "applyS"; t = tactic_term ; params = auto_params ->
302         G.ApplyS (loc, t, params)
303     | IDENT "assumption" ->
304         G.Assumption loc
305     | IDENT "autobatch";  params = auto_params ->
306         G.AutoBatch (loc,params)
307     | IDENT "cases"; what = tactic_term;
308       pattern = OPT pattern_spec;
309       specs = intros_spec ->
310         let pattern = match pattern with
311            | None         -> None, [], Some N.UserInput
312            | Some pattern -> pattern   
313         in
314         G.Cases (loc, what, pattern, specs)
315     | IDENT "clear"; ids = LIST1 IDENT ->
316         G.Clear (loc, ids)
317     | IDENT "clearbody"; id = IDENT ->
318         G.ClearBody (loc,id)
319     | IDENT "change"; what = pattern_spec; "with"; t = tactic_term ->
320         G.Change (loc, what, t)
321     | IDENT "compose"; times = OPT int; t1 = tactic_term; t2 = 
322       OPT [ "with"; t = tactic_term -> t ]; specs = intros_spec ->
323         let times = match times with None -> 1 | Some i -> i in
324         G.Compose (loc, t1, t2, times, specs)
325     | IDENT "constructor"; n = int ->
326         G.Constructor (loc, n)
327     | IDENT "contradiction" ->
328         G.Contradiction loc
329     | IDENT "cut"; t = tactic_term; ident = OPT [ "as"; id = IDENT -> id] ->
330         G.Cut (loc, ident, t)
331     | IDENT "decompose"; idents = OPT [ "as"; idents = LIST1 new_name -> idents ] ->
332         let idents = match idents with None -> [] | Some idents -> idents in
333         G.Decompose (loc, idents)
334     | IDENT "demodulate"; p = auto_params -> G.Demodulate (loc, p)
335     | IDENT "destruct"; xts = OPT [ ts = tactic_term_list1 -> ts ] ->
336         G.Destruct (loc, xts)
337     | IDENT "elim"; what = tactic_term; using = using; 
338        pattern = OPT pattern_spec;
339        ispecs = intros_spec ->
340         let pattern = match pattern with
341            | None         -> None, [], Some N.UserInput
342            | Some pattern -> pattern   
343           in
344           G.Elim (loc, what, using, pattern, ispecs)
345     | IDENT "elimType"; what = tactic_term; using = using;
346       (num, idents) = intros_spec ->
347         G.ElimType (loc, what, using, (num, idents))
348     | IDENT "exact"; t = tactic_term ->
349         G.Exact (loc, t)
350     | IDENT "exists" ->
351         G.Exists loc
352     | IDENT "fail" -> G.Fail loc
353     | IDENT "fold"; kind = reduction_kind; t = tactic_term; p = pattern_spec ->
354         let (pt,_,_) = p in
355           if pt <> None then
356             raise (HExtlib.Localized (loc, CicNotationParser.Parse_error
357               ("the pattern cannot specify the term to replace, only its"
358               ^ " paths in the hypotheses and in the conclusion")))
359        else
360          G.Fold (loc, kind, t, p)
361     | IDENT "fourier" ->
362         G.Fourier loc
363     | IDENT "fwd"; hyp = IDENT; idents = OPT [ "as"; idents = LIST1 new_name -> idents ] ->
364         let idents = match idents with None -> [] | Some idents -> idents in
365         G.FwdSimpl (loc, hyp, idents)
366     | IDENT "generalize"; p=pattern_spec; id = OPT ["as" ; id = IDENT -> id] ->
367        G.Generalize (loc,p,id)
368     | IDENT "id" -> G.IdTac loc
369     | IDENT "intro"; ident = OPT IDENT ->
370         let idents = match ident with None -> [] | Some id -> [Some id] in
371         G.Intros (loc, (Some 1, idents))
372     | IDENT "intros"; specs = intros_spec ->
373         G.Intros (loc, specs)
374     | IDENT "inversion"; t = tactic_term ->
375         G.Inversion (loc, t)
376     | IDENT "lapply"; 
377       linear = OPT [ IDENT "linear" ];
378       depth = OPT [ IDENT "depth"; SYMBOL "="; i = int -> i ];
379       what = tactic_term; 
380       to_what = OPT [ "to" ; t = tactic_term_list1 -> t ];
381       ident = OPT [ "as" ; ident = IDENT -> ident ] ->
382         let linear = match linear with None -> false | Some _ -> true in 
383         let to_what = match to_what with None -> [] | Some to_what -> to_what in
384         G.LApply (loc, linear, depth, to_what, what, ident)
385     | IDENT "left" -> G.Left loc
386     | IDENT "letin"; where = IDENT ; SYMBOL <:unicode<def>> ; t = tactic_term ->
387         G.LetIn (loc, t, where)
388     | kind = reduction_kind; p = pattern_spec ->
389         G.Reduce (loc, kind, p)
390     | IDENT "reflexivity" ->
391         G.Reflexivity loc
392     | IDENT "replace"; p = pattern_spec; "with"; t = tactic_term ->
393         G.Replace (loc, p, t)
394     | IDENT "rewrite" ; d = direction; t = tactic_term ; p = pattern_spec;
395        xnames = OPT [ "as"; n = ident_list0 -> n ] ->
396        let (pt,_,_) = p in
397         if pt <> None then
398          raise
399           (HExtlib.Localized (loc,
400            (CicNotationParser.Parse_error
401             "the pattern cannot specify the term to rewrite, only its paths in the hypotheses and in the conclusion")))
402         else
403          let n = match xnames with None -> [] | Some names -> names in 
404          G.Rewrite (loc, d, t, p, n)
405     | IDENT "right" ->
406         G.Right loc
407     | IDENT "ring" ->
408         G.Ring loc
409     | IDENT "split" ->
410         G.Split loc
411     | IDENT "symmetry" ->
412         G.Symmetry loc
413     | IDENT "transitivity"; t = tactic_term ->
414         G.Transitivity (loc, t)
415      (* Produzioni Aggiunte *)
416     | IDENT "assume" ; id = IDENT ; SYMBOL ":" ; t = tactic_term ->
417         G.Assume (loc, id, t)
418     | IDENT "suppose" ; t = tactic_term ; LPAREN ; id = IDENT ; RPAREN ; 
419       t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ; 
420                 t' = tactic_term -> t']->
421         G.Suppose (loc, t, id, t1)
422     | "let" ; id1 = IDENT ; SYMBOL ":" ; t1 = tactic_term ;
423       IDENT "such" ; IDENT "that" ; t2=tactic_term ; LPAREN ; 
424       id2 = IDENT ; RPAREN -> 
425         G.ExistsElim (loc, `Auto ([],[]), id1, t1, id2, t2)
426     | just =
427        [ IDENT "using"; t=tactic_term -> `Term t
428        | params = auto_params -> `Auto params] ;
429       cont=by_continuation ->
430        (match cont with
431            BYC_done -> G.Bydone (loc, just)
432          | BYC_weproved (ty,id,t1) ->
433             G.By_just_we_proved(loc, just, ty, id, t1)
434          | BYC_letsuchthat (id1,t1,id2,t2) ->
435             G.ExistsElim (loc, just, id1, t1, id2, t2)
436          | BYC_wehaveand (id1,t1,id2,t2) ->
437             G.AndElim (loc, just, id1, t1, id2, t2))
438     | IDENT "we" ; IDENT "need" ; "to" ; IDENT "prove" ; t = tactic_term ; id = OPT [ LPAREN ; id = IDENT ; RPAREN -> id ] ; t1 = OPT [IDENT "or" ; IDENT "equivalently"; t' = tactic_term -> t']->
439         G.We_need_to_prove (loc, t, id, t1)
440     | IDENT "we" ; IDENT "proceed" ; IDENT "by" ; IDENT "cases" ; "on" ; t=tactic_term ; "to" ; IDENT "prove" ; t1=tactic_term ->  
441         G.We_proceed_by_cases_on (loc, t, t1)
442     | IDENT "we" ; IDENT "proceed" ; IDENT "by" ; IDENT "induction" ; "on" ; t=tactic_term ; "to" ; IDENT "prove" ; t1=tactic_term ->  
443         G.We_proceed_by_induction_on (loc, t, t1)
444     | IDENT "by" ; IDENT "induction" ; IDENT "hypothesis" ; IDENT "we" ; IDENT "know" ; t=tactic_term ; LPAREN ; id = IDENT ; RPAREN ->
445         G.Byinduction(loc, t, id)
446     | IDENT "the" ; IDENT "thesis" ; IDENT "becomes" ; t=tactic_term ->
447         G.Thesisbecomes(loc, t)
448     | IDENT "case" ; id = IDENT ; params=LIST0[LPAREN ; i=IDENT ;
449         SYMBOL":" ; t=tactic_term ; RPAREN -> i,t] ->
450          G.Case(loc,id,params)
451       (* DO NOT FACTORIZE with the two following, camlp5 sucks*)
452     | IDENT "conclude"; 
453       termine = tactic_term;
454       SYMBOL "=" ;
455       t1=tactic_term ;
456       t2 =
457        [ IDENT "using"; t=tactic_term -> `Term t
458        | IDENT "using"; IDENT "once"; term=tactic_term -> `SolveWith term
459        | IDENT "proof" -> `Proof
460        | params = auto_params -> `Auto params];
461       cont = rewriting_step_continuation ->
462        G.RewritingStep(loc, Some (None,termine), t1, t2, cont)
463     | IDENT "obtain" ; name = IDENT;
464       termine = tactic_term;
465       SYMBOL "=" ;
466       t1=tactic_term ;
467       t2 =
468        [ IDENT "using"; t=tactic_term -> `Term t
469        | IDENT "using"; IDENT "once"; term=tactic_term -> `SolveWith term
470        | IDENT "proof" -> `Proof
471        | params = auto_params -> `Auto params];
472       cont = rewriting_step_continuation ->
473        G.RewritingStep(loc, Some (Some name,termine), t1, t2, cont)
474     | SYMBOL "=" ;
475       t1=tactic_term ;
476       t2 =
477        [ IDENT "using"; t=tactic_term -> `Term t
478        | IDENT "using"; IDENT "once"; term=tactic_term -> `SolveWith term
479        | IDENT "proof" -> `Proof
480        | params = auto_params -> `Auto params];
481       cont = rewriting_step_continuation ->
482        G.RewritingStep(loc, None, t1, t2, cont)
483   ]
484 ];
485   auto_fixed_param: [
486    [ IDENT "paramodulation"
487    | IDENT "fast_paramod"
488    | IDENT "paramod"
489    | IDENT "slir"
490    | IDENT "depth"
491    | IDENT "width"
492    | IDENT "size"
493    | IDENT "timeout"
494    | IDENT "library"
495    | IDENT "type"
496    | IDENT "all"
497    ]
498 ];
499   auto_params: [
500    [ params =
501       LIST0 [
502          i = auto_fixed_param -> i,""
503        | i = auto_fixed_param ; SYMBOL "="; v = [ v = int ->
504               string_of_int v | v = IDENT -> v ] -> i,v ]; 
505       tl = OPT [ IDENT "by"; tl = tactic_term_list1 -> tl] ->
506       (match tl with Some l -> l | None -> []),
507       params
508    ]
509 ];
510   inline_params:[
511    [ params = LIST0 
512       [ IDENT "prefix"; SYMBOL "="; prefix = QSTRING -> G.IPPrefix prefix  
513       | flavour = inline_flavour -> G.IPAs flavour
514       | IDENT "coercions" -> G.IPCoercions
515       | IDENT "debug"; SYMBOL "="; debug = int -> G.IPDebug debug 
516       | IDENT "procedural" -> G.IPProcedural
517       | IDENT "nodefaults" -> G.IPNoDefaults
518       | IDENT "depth"; SYMBOL "="; depth = int -> G.IPDepth depth 
519       | IDENT "level"; SYMBOL "="; level = int -> G.IPLevel level 
520       | IDENT "comments" -> G.IPComments
521       | IDENT "cr" -> G.IPCR
522       ] -> params
523    ]
524 ];
525   by_continuation: [
526     [ WEPROVED; ty = tactic_term ; LPAREN ; id = IDENT ; RPAREN ; t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ; t2 = tactic_term -> t2] -> BYC_weproved (ty,Some id,t1)
527     | WEPROVED; ty = tactic_term ; t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ; t2 = tactic_term -> t2] ; 
528             "done" -> BYC_weproved (ty,None,t1)
529     | "done" -> BYC_done
530     | "let" ; id1 = IDENT ; SYMBOL ":" ; t1 = tactic_term ;
531       IDENT "such" ; IDENT "that" ; t2=tactic_term ; LPAREN ; 
532       id2 = IDENT ; RPAREN -> BYC_letsuchthat (id1,t1,id2,t2)
533     | WEHAVE; t1=tactic_term ; LPAREN ; id1=IDENT ; RPAREN ;"and" ; t2=tactic_term ; LPAREN ; id2=IDENT ; RPAREN ->
534               BYC_wehaveand (id1,t1,id2,t2)
535     ]
536 ];
537   rewriting_step_continuation : [
538     [ "done" -> true
539     | -> false
540     ]
541 ];
542   atomic_tactical:
543     [ "sequence" LEFTA
544       [ t1 = SELF; SYMBOL ";"; t2 = SELF ->
545           let ts =
546             match t1 with
547             | G.Seq (_, l) -> l @ [ t2 ]
548             | _ -> [ t1; t2 ]
549           in
550           G.Seq (loc, ts)
551       ]
552     | "then" NONA
553       [ tac = SELF; SYMBOL ";";
554         SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
555           (G.Then (loc, tac, tacs))
556       ]
557     | "loops" RIGHTA
558       [ IDENT "do"; count = int; tac = SELF ->
559           G.Do (loc, count, tac)
560       | IDENT "repeat"; tac = SELF -> G.Repeat (loc, tac)
561       ]
562     | "simple" NONA
563       [ IDENT "first";
564         SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
565           G.First (loc, tacs)
566       | IDENT "try"; tac = SELF -> G.Try (loc, tac)
567       | IDENT "solve";
568         SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
569           G.Solve (loc, tacs)
570       | IDENT "progress"; tac = SELF -> G.Progress (loc, tac)
571       | LPAREN; tac = SELF; RPAREN -> tac
572       | tac = tactic -> tac
573         ]
574       ];
575   npunctuation_tactical:
576     [
577       [ SYMBOL "[" -> G.NBranch loc
578       | SYMBOL "|" -> G.NShift loc
579       | i = LIST1 int SEP SYMBOL ","; SYMBOL ":" -> G.NPos (loc, i)
580       | SYMBOL "*"; SYMBOL ":" -> G.NWildcard loc
581       | name = IDENT; SYMBOL ":" -> G.NPosbyname (loc, name)
582       | SYMBOL "]" -> G.NMerge loc
583       | SYMBOL ";" -> G.NSemicolon loc
584       | SYMBOL "." -> G.NDot loc
585       ]
586     ];
587   punctuation_tactical:
588     [
589       [ SYMBOL "[" -> G.Branch loc
590       | SYMBOL "|" -> G.Shift loc
591       | i = LIST1 int SEP SYMBOL ","; SYMBOL ":" -> G.Pos (loc, i)
592       | SYMBOL "*"; SYMBOL ":" -> G.Wildcard loc
593       | SYMBOL "]" -> G.Merge loc
594       | SYMBOL ";" -> G.Semicolon loc
595       | SYMBOL "." -> G.Dot loc
596       ]
597     ];
598   non_punctuation_tactical:
599     [ "simple" NONA
600       [ IDENT "focus"; goals = LIST1 int -> G.Focus (loc, goals)
601       | IDENT "unfocus" -> G.Unfocus loc
602       | IDENT "skip" -> G.Skip loc
603       ]
604       ];
605   ntheorem_flavour: [
606     [ [ IDENT "ndefinition"  ] -> `Definition
607     | [ IDENT "nfact"        ] -> `Fact
608     | [ IDENT "nlemma"       ] -> `Lemma
609     | [ IDENT "nremark"      ] -> `Remark
610     | [ IDENT "ntheorem"     ] -> `Theorem
611     ]
612   ];
613   theorem_flavour: [
614     [ [ IDENT "definition"  ] -> `Definition
615     | [ IDENT "fact"        ] -> `Fact
616     | [ IDENT "lemma"       ] -> `Lemma
617     | [ IDENT "remark"      ] -> `Remark
618     | [ IDENT "theorem"     ] -> `Theorem
619     ]
620   ];
621   inline_flavour: [
622      [ attr = theorem_flavour -> attr
623      | [ IDENT "axiom"     ]  -> `Axiom
624      | [ IDENT "variant"   ]  -> `Variant
625      ]
626   ];
627   inductive_spec: [ [
628     fst_name = IDENT; 
629       params = LIST0 protected_binder_vars;
630     SYMBOL ":"; fst_typ = term; SYMBOL <:unicode<def>>; OPT SYMBOL "|";
631     fst_constructors = LIST0 constructor SEP SYMBOL "|";
632     tl = OPT [ "with";
633         types = LIST1 [
634           name = IDENT; SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>;
635          OPT SYMBOL "|"; constructors = LIST0 constructor SEP SYMBOL "|" ->
636             (name, true, typ, constructors) ] SEP "with" -> types
637       ] ->
638         let params =
639           List.fold_right
640             (fun (names, typ) acc ->
641               (List.map (fun name -> (name, typ)) names) @ acc)
642             params []
643         in
644         let fst_ind_type = (fst_name, true, fst_typ, fst_constructors) in
645         let tl_ind_types = match tl with None -> [] | Some types -> types in
646         let ind_types = fst_ind_type :: tl_ind_types in
647         (params, ind_types)
648     ] ];
649     
650     record_spec: [ [
651       name = IDENT; 
652       params = LIST0 protected_binder_vars;
653        SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>; SYMBOL "{" ; 
654        fields = LIST0 [ 
655          name = IDENT ; 
656          coercion = [ 
657              SYMBOL ":" -> false,0 
658            | SYMBOL ":"; SYMBOL ">" -> true,0
659            | SYMBOL ":"; arity = int ; SYMBOL ">" -> true,arity
660          ]; 
661          ty = term -> 
662            let b,n = coercion in 
663            (name,ty,b,n) 
664        ] SEP SYMBOL ";"; SYMBOL "}" -> 
665         let params =
666           List.fold_right
667             (fun (names, typ) acc ->
668               (List.map (fun name -> (name, typ)) names) @ acc)
669             params []
670         in
671         (params,name,typ,fields)
672     ] ];
673
674     nmacro: [
675       [ [ IDENT "ncheck" ]; t = term -> G.NCheck (loc,t)
676       | [ IDENT "screenshot"]; fname = QSTRING -> G.Screenshot (loc, fname)
677       ]
678     ];
679     
680     macro: [
681       [ [ IDENT "check"   ]; t = term ->
682           G.Check (loc, t)
683       | [ IDENT "eval" ]; kind = reduction_kind; "on"; t = tactic_term ->
684           G.Eval (loc, kind, t)
685       | IDENT "inline"; suri = QSTRING; params = inline_params -> 
686            G.Inline (loc, suri, params)
687       | [ IDENT "hint" ]; rew = OPT (IDENT "rewrite")  -> 
688            if rew = None then G.Hint (loc, false) else G.Hint (loc,true)
689       | IDENT "auto"; params = auto_params ->
690           G.AutoInteractive (loc,params)
691       | [ IDENT "whelp"; "match" ] ; t = term -> 
692           G.WMatch (loc,t)
693       | [ IDENT "whelp"; IDENT "instance" ] ; t = term -> 
694           G.WInstance (loc,t)
695       | [ IDENT "whelp"; IDENT "locate" ] ; id = QSTRING -> 
696           G.WLocate (loc,id)
697       | [ IDENT "whelp"; IDENT "elim" ] ; t = term ->
698           G.WElim (loc, t)
699       | [ IDENT "whelp"; IDENT "hint" ] ; t = term -> 
700           G.WHint (loc,t)
701       ]
702     ];
703     alias_spec: [
704       [ IDENT "id"; id = QSTRING; SYMBOL "="; uri = QSTRING ->
705         let alpha = "[a-zA-Z]" in
706         let num = "[0-9]+" in
707         let ident_cont = "\\("^alpha^"\\|"^num^"\\|_\\|\\\\\\)" in
708         let decoration = "\\'" in
709         let ident = "\\("^alpha^ident_cont^"*"^decoration^"*\\|_"^ident_cont^"+"^decoration^"*\\)" in
710         let rex = Str.regexp ("^"^ident^"$") in
711         if Str.string_match rex id 0 then
712           if (try ignore (UriManager.uri_of_string uri); true
713               with UriManager.IllFormedUri _ -> false) ||
714              (try ignore (NReference.reference_of_string uri); true
715               with NReference.IllFormedReference _ -> false)
716           then
717             L.Ident_alias (id, uri)
718           else
719             raise
720              (HExtlib.Localized (loc, CicNotationParser.Parse_error (Printf.sprintf "Not a valid uri: %s" uri)))
721         else
722           raise (HExtlib.Localized (loc, CicNotationParser.Parse_error (
723             Printf.sprintf "Not a valid identifier: %s" id)))
724       | IDENT "symbol"; symbol = QSTRING;
725         instance = OPT [ LPAREN; IDENT "instance"; n = int; RPAREN -> n ];
726         SYMBOL "="; dsc = QSTRING ->
727           let instance =
728             match instance with Some i -> i | None -> 0
729           in
730           L.Symbol_alias (symbol, instance, dsc)
731       | IDENT "num";
732         instance = OPT [ LPAREN; IDENT "instance"; n = int; RPAREN -> n ];
733         SYMBOL "="; dsc = QSTRING ->
734           let instance =
735             match instance with Some i -> i | None -> 0
736           in
737           L.Number_alias (instance, dsc)
738       ]
739      ];
740     argument: [
741       [ l = LIST0 [ SYMBOL <:unicode<eta>> (* η *); SYMBOL "." -> () ];
742         id = IDENT ->
743           N.IdentArg (List.length l, id)
744       ]
745     ];
746     associativity: [
747       [ IDENT "left";  IDENT "associative" -> Gramext.LeftA
748       | IDENT "right"; IDENT "associative" -> Gramext.RightA
749       | IDENT "non"; IDENT "associative" -> Gramext.NonA
750       ]
751     ];
752     precedence: [
753       [ "with"; IDENT "precedence"; n = NUMBER -> int_of_string n ]
754     ];
755     notation: [
756       [ dir = OPT direction; s = QSTRING;
757         assoc = OPT associativity; prec = precedence;
758         IDENT "for";
759         p2 = 
760           [ blob = UNPARSED_AST ->
761               add_raw_attribute ~text:(Printf.sprintf "@{%s}" blob)
762                 (CicNotationParser.parse_level2_ast
763                   (Ulexing.from_utf8_string blob))
764           | blob = UNPARSED_META ->
765               add_raw_attribute ~text:(Printf.sprintf "${%s}" blob)
766                 (CicNotationParser.parse_level2_meta
767                   (Ulexing.from_utf8_string blob))
768           ] ->
769             let assoc =
770               match assoc with
771               | None -> default_associativity
772               | Some assoc -> assoc
773             in
774             let p1 =
775               add_raw_attribute ~text:s
776                 (CicNotationParser.parse_level1_pattern prec
777                   (Ulexing.from_utf8_string s))
778             in
779             (dir, p1, assoc, prec, p2)
780       ]
781     ];
782     level3_term: [
783       [ u = URI -> N.UriPattern (UriManager.uri_of_string u)
784       | r = NREF -> N.NRefPattern (NReference.reference_of_string r)
785       | IMPLICIT -> N.ImplicitPattern
786       | id = IDENT -> N.VarPattern id
787       | LPAREN; terms = LIST1 SELF; RPAREN ->
788           (match terms with
789           | [] -> assert false
790           | [term] -> term
791           | terms -> N.ApplPattern terms)
792       ]
793     ];
794     interpretation: [
795       [ s = CSYMBOL; args = LIST0 argument; SYMBOL "="; t = level3_term ->
796           (s, args, t)
797       ]
798     ];
799     
800     include_command: [ [
801         IDENT "include" ; path = QSTRING -> 
802           loc,path,true,L.WithPreferences
803       | IDENT "include" ; IDENT "source" ; path = QSTRING -> 
804           loc,path,false,L.WithPreferences        
805       | IDENT "include'" ; path = QSTRING -> 
806           loc,path,true,L.WithoutPreferences
807      ]];
808
809   grafite_ncommand: [ [
810       IDENT "nqed" -> G.NQed loc
811     | nflavour = ntheorem_flavour; name = IDENT; SYMBOL ":"; typ = term;
812       body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
813         G.NObj (loc, N.Theorem (nflavour, name, typ, body,`Regular))
814     | nflavour = ntheorem_flavour; name = IDENT; SYMBOL <:unicode<def>> (* ≝ *);
815       body = term ->
816         G.NObj (loc, N.Theorem (nflavour, name, N.Implicit `JustOne, Some body,`Regular))
817     | IDENT "naxiom"; name = IDENT; SYMBOL ":"; typ = term ->
818         G.NObj (loc, N.Theorem (`Axiom, name, typ, None, `Regular))
819     | IDENT "ndiscriminator" ; indty = tactic_term -> G.NDiscriminator (loc,indty)
820     | IDENT "ninverter"; name = IDENT; IDENT "for" ; indty = tactic_term ;
821       paramspec = OPT inverter_param_list ; 
822       outsort = OPT [ SYMBOL ":" ; outsort = term -> outsort ] -> 
823         G.NInverter (loc,name,indty,paramspec,outsort)
824     | NLETCOREC ; defs = let_defs -> 
825         nmk_rec_corec `CoInductive defs loc
826     | NLETREC ; defs = let_defs -> 
827         nmk_rec_corec `Inductive defs loc
828     | IDENT "ninductive"; spec = inductive_spec ->
829         let (params, ind_types) = spec in
830         G.NObj (loc, N.Inductive (params, ind_types))
831     | IDENT "ncoinductive"; spec = inductive_spec ->
832         let (params, ind_types) = spec in
833         let ind_types = (* set inductive flags to false (coinductive) *)
834           List.map (fun (name, _, term, ctors) -> (name, false, term, ctors))
835             ind_types
836         in
837         G.NObj (loc, N.Inductive (params, ind_types))
838     | IDENT "universe"; IDENT "constraint"; u1 = tactic_term; 
839         SYMBOL <:unicode<lt>> ; u2 = tactic_term ->
840         let urify = function 
841           | CicNotationPt.AttributedTerm (_, CicNotationPt.Sort (`NType i)) ->
842               NUri.uri_of_string ("cic:/matita/pts/Type"^i^".univ")
843           | _ -> raise (Failure "only a Type[…] sort can be constrained")
844         in
845         let u1 = urify u1 in
846         let u2 = urify u2 in
847          G.NUnivConstraint (loc,u1,u2)
848     | IDENT "unification"; IDENT "hint"; n = int; t = tactic_term ->
849         G.UnificationHint (loc, t, n)
850     | IDENT "ncoercion"; name = IDENT; SYMBOL ":"; ty = term; 
851         SYMBOL <:unicode<def>>; t = term; "on"; 
852         id = [ IDENT | PIDENT ]; SYMBOL ":"; source = term;
853         "to"; target = term ->
854           G.NCoercion(loc,name,t,ty,(id,source),target)     
855     | IDENT "nrecord" ; (params,name,ty,fields) = record_spec ->
856         G.NObj (loc, N.Record (params,name,ty,fields))
857     | IDENT "ncopy" ; s = IDENT; IDENT "from"; u = URI; "with"; 
858       m = LIST0 [ u1 = URI; SYMBOL <:unicode<mapsto>>; u2 = URI -> u1,u2 ] ->
859         G.NCopy (loc,s,NUri.uri_of_string u,
860           List.map (fun a,b -> NUri.uri_of_string a, NUri.uri_of_string b) m)
861   ]];
862
863   grafite_command: [ [
864       IDENT "set"; n = QSTRING; v = QSTRING ->
865         G.Set (loc, n, v)
866     | IDENT "drop" -> G.Drop loc
867     | IDENT "print"; s = IDENT -> G.Print (loc,s)
868     | IDENT "qed" -> G.Qed loc
869     | IDENT "variant" ; name = IDENT; SYMBOL ":"; 
870       typ = term; SYMBOL <:unicode<def>> ; newname = IDENT ->
871         G.Obj (loc, 
872           N.Theorem 
873             (`Variant,name,typ,Some (N.Ident (newname, None)), `Regular))
874     | flavour = theorem_flavour; name = IDENT; SYMBOL ":"; typ = term;
875       body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
876         G.Obj (loc, N.Theorem (flavour, name, typ, body,`Regular))
877     | flavour = theorem_flavour; name = IDENT; SYMBOL <:unicode<def>> (* ≝ *);
878       body = term ->
879         G.Obj (loc,
880           N.Theorem (flavour, name, N.Implicit `JustOne, Some body,`Regular))
881     | IDENT "axiom"; name = IDENT; SYMBOL ":"; typ = term ->
882         G.Obj (loc, N.Theorem (`Axiom, name, typ, None, `Regular))
883     | LETCOREC ; defs = let_defs -> 
884         mk_rec_corec `CoInductive defs loc
885     | LETREC ; defs = let_defs -> 
886         mk_rec_corec `Inductive defs loc
887     | IDENT "inductive"; spec = inductive_spec ->
888         let (params, ind_types) = spec in
889         G.Obj (loc, N.Inductive (params, ind_types))
890     | IDENT "coinductive"; spec = inductive_spec ->
891         let (params, ind_types) = spec in
892         let ind_types = (* set inductive flags to false (coinductive) *)
893           List.map (fun (name, _, term, ctors) -> (name, false, term, ctors))
894             ind_types
895         in
896         G.Obj (loc, N.Inductive (params, ind_types))
897     | IDENT "coercion" ; 
898       t = [ u = URI -> N.Uri (u,None) | t = tactic_term ; OPT "with" -> t ] ;
899       arity = OPT int ; saturations = OPT int; 
900       composites = OPT (IDENT "nocomposites") ->
901         let arity = match arity with None -> 0 | Some x -> x in
902         let saturations = match saturations with None -> 0 | Some x -> x in
903         let composites = match composites with None -> true | Some _ -> false in
904         G.Coercion
905          (loc, t, composites, arity, saturations)
906     | IDENT "prefer" ; IDENT "coercion"; t = tactic_term ->
907         G.PreferCoercion (loc, t)
908     | IDENT "pump" ; steps = int ->
909         G.Pump(loc,steps)
910     | IDENT "inverter"; name = IDENT; IDENT "for";
911         indty = tactic_term; paramspec = inverter_param_list ->
912           G.Inverter
913             (loc, name, indty, paramspec)
914     | IDENT "record" ; (params,name,ty,fields) = record_spec ->
915         G.Obj (loc, N.Record (params,name,ty,fields))
916     | IDENT "default" ; what = QSTRING ; uris = LIST1 URI ->
917        let uris = List.map UriManager.uri_of_string uris in
918         G.Default (loc,what,uris)
919     | IDENT "relation" ; aeq = tactic_term ; "on" ; a = tactic_term ;
920       refl = OPT [ IDENT "reflexivity" ; IDENT "proved" ; IDENT "by" ;
921                    refl = tactic_term -> refl ] ;
922       sym = OPT [ IDENT "symmetry" ; IDENT "proved" ; IDENT "by" ;
923                    sym = tactic_term -> sym ] ;
924       trans = OPT [ IDENT "transitivity" ; IDENT "proved" ; IDENT "by" ;
925                    trans = tactic_term -> trans ] ;
926       "as" ; id = IDENT ->
927        G.Relation (loc,id,a,aeq,refl,sym,trans)
928   ]];
929   lexicon_command: [ [
930       IDENT "alias" ; spec = alias_spec ->
931         L.Alias (loc, spec)
932     | IDENT "notation"; (dir, l1, assoc, prec, l2) = notation ->
933         L.Notation (loc, dir, l1, assoc, prec, l2)
934     | IDENT "interpretation"; id = QSTRING;
935       (symbol, args, l3) = interpretation ->
936         L.Interpretation (loc, id, (symbol, args), l3)
937   ]];
938   executable: [
939     [ cmd = grafite_command; SYMBOL "." -> G.Command (loc, cmd)
940     | ncmd = grafite_ncommand; SYMBOL "." -> G.NCommand (loc, ncmd)
941     | tac = atomic_tactical LEVEL "loops"; punct = punctuation_tactical ->
942         G.Tactic (loc, Some tac, punct)
943     | punct = punctuation_tactical -> G.Tactic (loc, None, punct)
944     | tac = ntactic; SYMBOL "#" ; SYMBOL "#" ; punct = punctuation_tactical ->
945         G.NTactic (loc, [tac; npunct_of_punct punct])
946     | tac = ntactic; punct = punctuation_tactical ->
947         G.NTactic (loc, [tac; npunct_of_punct punct])
948     | SYMBOL "#" ; SYMBOL "#" ; punct = npunctuation_tactical ->
949         G.NTactic (loc, [punct])
950     | tac = non_punctuation_tactical; punct = punctuation_tactical ->
951         G.NonPunctuationTactical (loc, tac, punct)
952     | SYMBOL "#" ; SYMBOL "#" ; tac = non_punctuation_tactical; 
953         SYMBOL "#" ; SYMBOL "#" ; punct = punctuation_tactical ->
954           G.NTactic (loc, [nnon_punct_of_punct tac; npunct_of_punct punct])
955     | SYMBOL "#" ; SYMBOL "#" ; tac = non_punctuation_tactical; 
956         punct = punctuation_tactical ->
957           G.NTactic (loc, [nnon_punct_of_punct tac; npunct_of_punct punct])
958     | mac = macro; SYMBOL "." -> G.Macro (loc, mac)
959     | mac = nmacro; SYMBOL "." -> G.NMacro (loc, mac)
960     ]
961   ];
962   comment: [
963     [ BEGINCOMMENT ; ex = executable ; ENDCOMMENT -> 
964        G.Code (loc, ex)
965     | str = NOTE -> 
966        G.Note (loc, str)
967     ]
968   ];
969   statement: [
970     [ ex = executable ->
971        fun ?(never_include=false) ~include_paths status ->
972           let stm = G.Executable (loc, ex) in
973           !grafite_callback stm;
974           status, LSome stm
975     | com = comment ->
976        fun ?(never_include=false) ~include_paths status -> 
977           let stm = G.Comment (loc, com) in
978           !grafite_callback stm;
979           status, LSome stm
980     | (iloc,fname,normal,mode) = include_command ; SYMBOL "."  ->
981        fun ?(never_include=false) ~include_paths status ->
982         let _root, buri, fullpath, _rrelpath = 
983           Librarian.baseuri_of_script ~include_paths fname in
984         if never_include then raise (NoInclusionPerformed fullpath)
985         else
986          begin
987           let stm =
988            G.Executable
989             (loc, G.Command (loc, G.Include (iloc,normal,`OldAndNew,fname))) in
990           !grafite_callback stm;
991           let status =
992            LE.eval_command status (L.Include (iloc,buri,mode,fullpath)) in
993           let stm =
994            G.Executable
995             (loc,G.Command (loc,G.Include (iloc,normal,`OldAndNew,buri)))
996           in
997            status, LSome stm
998          end
999     | scom = lexicon_command ; SYMBOL "." ->
1000        fun ?(never_include=false) ~include_paths status ->
1001           !lexicon_callback scom;         
1002           let status = LE.eval_command status scom in
1003           status, LNone loc
1004     | EOI -> raise End_of_file
1005     ]
1006   ];
1007 END
1008 (* }}} *)
1009 ;;
1010
1011 let _ = initialize_parser () ;;
1012
1013 let exc_located_wrapper f =
1014   try
1015     f ()
1016   with
1017   | Stdpp.Exc_located (_, End_of_file) -> raise End_of_file
1018   | Stdpp.Exc_located (floc, Stream.Error msg) ->
1019       raise (HExtlib.Localized (floc,CicNotationParser.Parse_error msg))
1020   | Stdpp.Exc_located (floc, HExtlib.Localized(_,exn)) ->
1021       raise
1022        (HExtlib.Localized (floc,CicNotationParser.Parse_error (Printexc.to_string exn)))
1023   | Stdpp.Exc_located (floc, exn) ->
1024       raise
1025        (HExtlib.Localized (floc,CicNotationParser.Parse_error (Printexc.to_string exn)))
1026
1027 let parse_statement lexbuf =
1028   exc_located_wrapper
1029     (fun () -> (Grammar.Entry.parse (Obj.magic !grafite_parser.statement) (Obj.magic lexbuf)))
1030
1031 let statement () = Obj.magic !grafite_parser.statement
1032
1033 let history = ref [] ;;
1034
1035 let push () =
1036   LexiconSync.push ();
1037   history := !grafite_parser :: !history;
1038   grafite_parser := initial_parser ();
1039   initialize_parser ()
1040 ;;
1041
1042 let pop () =
1043   LexiconSync.pop ();
1044   match !history with
1045   | [] -> assert false
1046   | gp :: tail ->
1047       grafite_parser := gp;
1048       history := tail
1049 ;;
1050
1051 (* vim:set foldmethod=marker: *)
1052
1053