]> matita.cs.unibo.it Git - helm.git/blob - components/grafite_parser/grafiteParser.ml
Procedural: some improvements
[helm.git] / 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 open Printf
29
30 module Ast = CicNotationPt
31
32 type 'a localized_option =
33    LSome of 'a
34  | LNone of GrafiteAst.loc
35
36 type ast_statement =
37   (CicNotationPt.term, CicNotationPt.term,
38    CicNotationPt.term GrafiteAst.reduction, 
39    CicNotationPt.term CicNotationPt.obj, string)
40     GrafiteAst.statement
41
42 type statement =
43   include_paths:string list ->
44   LexiconEngine.status ->
45     LexiconEngine.status * ast_statement localized_option
46
47 let grammar = CicNotationParser.level2_ast_grammar
48
49 let term = CicNotationParser.term
50 let statement = Grammar.Entry.create grammar "statement"
51
52 let add_raw_attribute ~text t = Ast.AttributedTerm (`Raw text, t)
53
54 let default_precedence = 50
55 let default_associativity = Gramext.NonA
56
57 type by_continuation =
58    BYC_done
59  | BYC_weproved of CicNotationPt.term * string option * CicNotationPt.term option
60  | BYC_letsuchthat of string * CicNotationPt.term * string * CicNotationPt.term
61  | BYC_wehaveand of string * CicNotationPt.term * string * CicNotationPt.term
62
63 EXTEND
64   GLOBAL: term statement;
65   constructor: [ [ name = IDENT; SYMBOL ":"; typ = term -> (name, typ) ] ];
66   tactic_term: [ [ t = term LEVEL "90N" -> t ] ];
67   ident_list0: [ [ LPAREN; idents = LIST0 IDENT; RPAREN -> idents ] ];
68   tactic_term_list1: [
69     [ tactic_terms = LIST1 tactic_term SEP SYMBOL "," -> tactic_terms ]
70   ];
71   reduction_kind: [
72     [ IDENT "normalize" -> `Normalize
73     | IDENT "reduce" -> `Reduce
74     | IDENT "simplify" -> `Simpl
75     | IDENT "unfold"; t = OPT tactic_term -> `Unfold t
76     | IDENT "whd" -> `Whd ]
77   ];
78   sequent_pattern_spec: [
79    [ hyp_paths =
80       LIST0
81        [ id = IDENT ;
82          path = OPT [SYMBOL ":" ; path = tactic_term -> path ] ->
83          (id,match path with Some p -> p | None -> Ast.UserInput) ];
84      goal_path = OPT [ SYMBOL <:unicode<vdash>>; term = tactic_term -> term ] ->
85       let goal_path =
86        match goal_path, hyp_paths with
87           None, [] -> Some Ast.UserInput
88         | None, _::_ -> None
89         | Some goal_path, _ -> Some goal_path
90       in
91        hyp_paths,goal_path
92    ]
93   ];
94   pattern_spec: [
95     [ res = OPT [
96        "in";
97        wanted_and_sps =
98         [ "match" ; wanted = tactic_term ;
99           sps = OPT [ "in"; sps = sequent_pattern_spec -> sps ] ->
100            Some wanted,sps
101         | sps = sequent_pattern_spec ->
102            None,Some sps
103         ] ->
104          let wanted,hyp_paths,goal_path =
105           match wanted_and_sps with
106              wanted,None -> wanted, [], Some Ast.UserInput
107            | wanted,Some (hyp_paths,goal_path) -> wanted,hyp_paths,goal_path
108          in
109           wanted, hyp_paths, goal_path ] ->
110       match res with
111          None -> None,[],Some Ast.UserInput
112        | Some ps -> ps]
113   ];
114   direction: [
115     [ SYMBOL ">" -> `LeftToRight
116     | SYMBOL "<" -> `RightToLeft ]
117   ];
118   int: [ [ num = NUMBER -> int_of_string num ] ];
119   intros_spec: [
120     [ OPT [ IDENT "names" ]; 
121       num = OPT [ num = int -> num ]; 
122       idents = OPT ident_list0 ->
123         let idents = match idents with None -> [] | Some idents -> idents in
124         num, idents
125     ]
126   ];
127   using: [ [ using = OPT [ IDENT "using"; t = tactic_term -> t ] -> using ] ];
128   tactic: [
129     [ IDENT "absurd"; t = tactic_term ->
130         GrafiteAst.Absurd (loc, t)
131     | IDENT "apply"; t = tactic_term ->
132         GrafiteAst.Apply (loc, t)
133     | IDENT "applyS"; t = tactic_term ; params = 
134         LIST0 [ i = IDENT -> i,"" | i = IDENT ; SYMBOL "="; v = [ v = int ->
135           string_of_int v | v = IDENT -> v ] -> i,v ] ->
136         GrafiteAst.ApplyS (loc, t, params)
137     | IDENT "assumption" ->
138         GrafiteAst.Assumption loc
139     | IDENT "auto"; params = auto_params ->
140         GrafiteAst.Auto (loc,params)
141     | IDENT "clear"; ids = LIST1 IDENT ->
142         GrafiteAst.Clear (loc, ids)
143     | IDENT "clearbody"; id = IDENT ->
144         GrafiteAst.ClearBody (loc,id)
145     | IDENT "change"; what = pattern_spec; "with"; t = tactic_term ->
146         GrafiteAst.Change (loc, what, t)
147     | IDENT "constructor"; n = int ->
148         GrafiteAst.Constructor (loc, n)
149     | IDENT "contradiction" ->
150         GrafiteAst.Contradiction loc
151     | IDENT "cut"; t = tactic_term; ident = OPT [ "as"; id = IDENT -> id] ->
152         GrafiteAst.Cut (loc, ident, t)
153     | IDENT "decompose"; types = OPT ident_list0; what = OPT IDENT;
154         idents = OPT [ "as"; idents = LIST1 IDENT -> idents ] ->
155         let types = match types with None -> [] | Some types -> types in
156         let idents = match idents with None -> [] | Some idents -> idents in
157         let to_spec id = GrafiteAst.Ident id in
158         GrafiteAst.Decompose (loc, List.rev_map to_spec types, what, idents)
159     | IDENT "demodulate" -> GrafiteAst.Demodulate loc
160     | IDENT "destruct"; t = tactic_term ->
161         GrafiteAst.Destruct (loc, t)
162     | IDENT "elim"; what = tactic_term; using = using;
163       (num, idents) = intros_spec ->
164         GrafiteAst.Elim (loc, what, using, num, idents)
165     | IDENT "elimType"; what = tactic_term; using = using;
166       (num, idents) = intros_spec ->
167         GrafiteAst.ElimType (loc, what, using, num, idents)
168     | IDENT "exact"; t = tactic_term ->
169         GrafiteAst.Exact (loc, t)
170     | IDENT "exists" ->
171         GrafiteAst.Exists loc
172     | IDENT "fail" -> GrafiteAst.Fail loc
173     | IDENT "fold"; kind = reduction_kind; t = tactic_term; p = pattern_spec ->
174         let (pt,_,_) = p in
175           if pt <> None then
176             raise (HExtlib.Localized (loc, CicNotationParser.Parse_error
177               ("the pattern cannot specify the term to replace, only its"
178               ^ " paths in the hypotheses and in the conclusion")))
179         else
180          GrafiteAst.Fold (loc, kind, t, p)
181     | IDENT "fourier" ->
182         GrafiteAst.Fourier loc
183     | IDENT "fwd"; hyp = IDENT; idents = OPT [ "as"; idents = LIST1 IDENT -> idents ] ->
184         let idents = match idents with None -> [] | Some idents -> idents in
185         GrafiteAst.FwdSimpl (loc, hyp, idents)
186     | IDENT "generalize"; p=pattern_spec; id = OPT ["as" ; id = IDENT -> id] ->
187        GrafiteAst.Generalize (loc,p,id)
188     | IDENT "goal"; n = int ->
189         GrafiteAst.Goal (loc, n)
190     | IDENT "id" -> GrafiteAst.IdTac loc
191     | IDENT "intro"; ident = OPT IDENT ->
192         let idents = match ident with None -> [] | Some id -> [id] in
193         GrafiteAst.Intros (loc, Some 1, idents)
194     | IDENT "intros"; (num, idents) = intros_spec ->
195         GrafiteAst.Intros (loc, num, idents)
196     | IDENT "inversion"; t = tactic_term ->
197         GrafiteAst.Inversion (loc, t)
198     | IDENT "lapply"; 
199       linear = OPT [ IDENT "linear" ];
200       depth = OPT [ IDENT "depth"; SYMBOL "="; i = int -> i ];
201       what = tactic_term; 
202       to_what = OPT [ "to" ; t = tactic_term_list1 -> t ];
203       ident = OPT [ "as" ; ident = IDENT -> ident ] ->
204         let linear = match linear with None -> false | Some _ -> true in 
205         let to_what = match to_what with None -> [] | Some to_what -> to_what in
206         GrafiteAst.LApply (loc, linear, depth, to_what, what, ident)
207     | IDENT "left" -> GrafiteAst.Left loc
208     | IDENT "letin"; where = IDENT ; SYMBOL <:unicode<def>> ; t = tactic_term ->
209         GrafiteAst.LetIn (loc, t, where)
210     | kind = reduction_kind; p = pattern_spec ->
211         GrafiteAst.Reduce (loc, kind, p)
212     | IDENT "reflexivity" ->
213         GrafiteAst.Reflexivity loc
214     | IDENT "replace"; p = pattern_spec; "with"; t = tactic_term ->
215         GrafiteAst.Replace (loc, p, t)
216     | IDENT "rewrite" ; d = direction; t = tactic_term ; p = pattern_spec ->
217        let (pt,_,_) = p in
218         if pt <> None then
219          raise
220           (HExtlib.Localized (loc,
221            (CicNotationParser.Parse_error
222             "the pattern cannot specify the term to rewrite, only its paths in the hypotheses and in the conclusion")))
223         else
224          GrafiteAst.Rewrite (loc, d, t, p)
225     | IDENT "right" ->
226         GrafiteAst.Right loc
227     | IDENT "ring" ->
228         GrafiteAst.Ring loc
229     | IDENT "split" ->
230         GrafiteAst.Split loc
231     | IDENT "subst" ->
232         GrafiteAst.Subst loc    
233     | IDENT "symmetry" ->
234         GrafiteAst.Symmetry loc
235     | IDENT "transitivity"; t = tactic_term ->
236         GrafiteAst.Transitivity (loc, t)
237      (* Produzioni Aggiunte *)
238     | IDENT "assume" ; id = IDENT ; SYMBOL ":" ; t = tactic_term ->
239         GrafiteAst.Assume (loc, id, t)
240     | IDENT "suppose" ; t = tactic_term ; LPAREN ; id = IDENT ; RPAREN ; t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ; t' = tactic_term -> t']->
241         GrafiteAst.Suppose (loc, t, id, t1)
242     | IDENT "by" ; t = [t' = tactic_term -> LSome t' | SYMBOL "_" -> LNone loc];
243       cont=by_continuation ->
244        let t' = match t with LNone _ -> None | LSome t -> Some t in
245        (match cont with
246            BYC_done -> GrafiteAst.Bydone (loc, t')
247          | BYC_weproved (ty,id,t1) ->
248             GrafiteAst.By_term_we_proved(loc, t', ty, id, t1)
249          | BYC_letsuchthat (id1,t1,id2,t2) ->
250             (match t with
251                 LNone floc ->
252                  raise (HExtlib.Localized
253                   (floc,CicNotationParser.Parse_error
254                     "tactic_term expected here"))
255               | LSome t -> GrafiteAst.ExistsElim (loc, t, id1, t1, id2, t2))
256          | BYC_wehaveand (id1,t1,id2,t2) ->
257             (match t with
258                 LNone floc ->
259                  raise (HExtlib.Localized
260                   (floc,CicNotationParser.Parse_error
261                     "tactic_term expected here"))
262               | LSome t -> GrafiteAst.AndElim (loc, t, id1, t1, id2, t2)))
263     | 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']->
264         GrafiteAst.We_need_to_prove (loc, t, id, t1)
265     | IDENT "we" ; IDENT "proceed" ; IDENT "by" ; IDENT "induction" ; "on" ; t=tactic_term ; "to" ; IDENT "prove" ; t1=tactic_term ->  
266         GrafiteAst.We_proceed_by_induction_on (loc, t, t1)
267     | IDENT "by" ; IDENT "induction" ; IDENT "hypothesis" ; IDENT "we" ; IDENT "know" ; t=tactic_term ; LPAREN ; id = IDENT ; RPAREN ->
268         GrafiteAst.Byinduction(loc, t, id)
269     | IDENT "the" ; IDENT "thesis" ; IDENT "becomes" ; t=tactic_term ->
270         GrafiteAst.Thesisbecomes(loc, t)
271     | IDENT "case" ; id = IDENT ; params=LIST0[LPAREN ; i=IDENT ;
272         SYMBOL":" ; t=tactic_term ; RPAREN -> i,t] ->
273          GrafiteAst.Case(loc,id,params)
274     | start=[IDENT "conclude" -> None | IDENT "obtain" ; name = IDENT -> Some name] ; termine=tactic_term ; SYMBOL "=" ; t1=tactic_term ; IDENT "by" ; t2=[ t=tactic_term -> `Term t | SYMBOL "_" ; params = auto_params' -> `Auto params  ] ; cont=rewriting_step_continuation ->
275      GrafiteAst.RewritingStep(loc, Some (start,termine), t1, t2, cont)
276     | SYMBOL "=" ; t1=tactic_term ; IDENT "by" ; t2=[ t=tactic_term -> `Term t | SYMBOL "_" ; params = auto_params' -> `Auto params ] ;
277       cont=rewriting_step_continuation  ->
278      GrafiteAst.RewritingStep(loc, None, t1, t2, cont)
279   ]
280 ];
281   auto_params: [
282    [ params =
283       LIST0 [ i = IDENT -> i,"" | i = IDENT ; SYMBOL "="; v = [ v = int ->
284        string_of_int v | v = IDENT -> v ] -> i,v ] ->
285       params
286    ]
287 ];
288   auto_params': [
289    [ LPAREN; params = auto_params; RPAREN -> params
290    | -> []
291    ]
292 ];
293   by_continuation: [
294     [ IDENT "we" ; IDENT "proved" ; 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)
295     | IDENT "we" ; IDENT "proved" ; ty = tactic_term ; t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ; t2 = tactic_term -> t2] ; 
296             IDENT "done" -> BYC_weproved (ty,None,t1)
297     | IDENT "done" -> BYC_done
298     | "let" ; id1 = IDENT ; SYMBOL ":" ; t1 = tactic_term ;
299       IDENT "such" ; IDENT "that" ; t2=tactic_term ; LPAREN ; id2 = IDENT ; RPAREN -> BYC_letsuchthat (id1,t1,id2,t2)
300     | IDENT "we" ; IDENT "have" ; t1=tactic_term ; LPAREN ; id1=IDENT ; RPAREN ;"and" ; t2=tactic_term ; LPAREN ; id2=IDENT ; RPAREN ->
301               BYC_wehaveand (id1,t1,id2,t2)
302     ]
303 ];
304   rewriting_step_continuation : [
305     [ IDENT "done" -> true
306     | -> false
307     ]
308 ];
309   atomic_tactical:
310     [ "sequence" LEFTA
311       [ t1 = SELF; SYMBOL ";"; t2 = SELF ->
312           let ts =
313             match t1 with
314             | GrafiteAst.Seq (_, l) -> l @ [ t2 ]
315             | _ -> [ t1; t2 ]
316           in
317           GrafiteAst.Seq (loc, ts)
318       ]
319     | "then" NONA
320       [ tac = SELF; SYMBOL ";";
321         SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
322           (GrafiteAst.Then (loc, tac, tacs))
323       ]
324     | "loops" RIGHTA
325       [ IDENT "do"; count = int; tac = SELF; IDENT "end" ->
326           GrafiteAst.Do (loc, count, tac)
327       | IDENT "repeat"; tac = SELF; IDENT "end" -> GrafiteAst.Repeat (loc, tac)
328       ]
329     | "simple" NONA
330       [ IDENT "first";
331         SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
332           GrafiteAst.First (loc, tacs)
333       | IDENT "try"; tac = SELF -> GrafiteAst.Try (loc, tac)
334       | IDENT "solve";
335         SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
336           GrafiteAst.Solve (loc, tacs)
337       | IDENT "progress"; tac = SELF -> GrafiteAst.Progress (loc, tac)
338       | LPAREN; tac = SELF; RPAREN -> tac
339       | tac = tactic -> GrafiteAst.Tactic (loc, tac)
340       ]
341     ];
342   punctuation_tactical:
343     [
344       [ SYMBOL "[" -> GrafiteAst.Branch loc
345       | SYMBOL "|" -> GrafiteAst.Shift loc
346       | i = LIST1 int SEP SYMBOL ","; SYMBOL ":" -> GrafiteAst.Pos (loc, i)
347       | SYMBOL "*"; SYMBOL ":" -> GrafiteAst.Wildcard loc
348       | SYMBOL "]" -> GrafiteAst.Merge loc
349       | SYMBOL ";" -> GrafiteAst.Semicolon loc
350       | SYMBOL "." -> GrafiteAst.Dot loc
351       ]
352     ];
353   tactical:
354     [ "simple" NONA
355       [ IDENT "focus"; goals = LIST1 int -> GrafiteAst.Focus (loc, goals)
356       | IDENT "unfocus" -> GrafiteAst.Unfocus loc
357       | IDENT "skip" -> GrafiteAst.Skip loc
358       | tac = atomic_tactical LEVEL "loops" -> tac
359       ]
360     ];
361   theorem_flavour: [
362     [ [ IDENT "definition"  ] -> `Definition
363     | [ IDENT "fact"        ] -> `Fact
364     | [ IDENT "lemma"       ] -> `Lemma
365     | [ IDENT "remark"      ] -> `Remark
366     | [ IDENT "theorem"     ] -> `Theorem
367     ]
368   ];
369   inductive_spec: [ [
370     fst_name = IDENT; params = LIST0 CicNotationParser.protected_binder_vars;
371     SYMBOL ":"; fst_typ = term; SYMBOL <:unicode<def>>; OPT SYMBOL "|";
372     fst_constructors = LIST0 constructor SEP SYMBOL "|";
373     tl = OPT [ "with";
374       types = LIST1 [
375         name = IDENT; SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>;
376        OPT SYMBOL "|"; constructors = LIST0 constructor SEP SYMBOL "|" ->
377           (name, true, typ, constructors) ] SEP "with" -> types
378     ] ->
379       let params =
380         List.fold_right
381           (fun (names, typ) acc ->
382             (List.map (fun name -> (name, typ)) names) @ acc)
383           params []
384       in
385       let fst_ind_type = (fst_name, true, fst_typ, fst_constructors) in
386       let tl_ind_types = match tl with None -> [] | Some types -> types in
387       let ind_types = fst_ind_type :: tl_ind_types in
388       (params, ind_types)
389   ] ];
390   
391   record_spec: [ [
392     name = IDENT; params = LIST0 CicNotationParser.protected_binder_vars ;
393      SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>; SYMBOL "{" ; 
394      fields = LIST0 [ 
395        name = IDENT ; 
396        coercion = [ 
397            SYMBOL ":" -> false,0 
398          | SYMBOL ":"; SYMBOL ">" -> true,0
399          | SYMBOL ":"; arity = int ; SYMBOL ">" -> true,arity
400        ]; 
401        ty = term -> 
402          let b,n = coercion in 
403          (name,ty,b,n) 
404      ] SEP SYMBOL ";"; SYMBOL "}" -> 
405       let params =
406         List.fold_right
407           (fun (names, typ) acc ->
408             (List.map (fun name -> (name, typ)) names) @ acc)
409           params []
410       in
411       (params,name,typ,fields)
412   ] ];
413   
414   macro: [
415     [ [ IDENT "check"   ]; t = term ->
416         GrafiteAst.Check (loc, t)
417     | [ IDENT "inline"]; 
418         style = OPT [ IDENT "procedural" ];
419         suri = QSTRING; prefix = OPT QSTRING ->
420          let style = match style with 
421             | None   -> GrafiteAst.Declarative
422             | Some _ -> GrafiteAst.Procedural
423          in
424          let prefix = match prefix with None -> "" | Some prefix -> prefix in
425          GrafiteAst.Inline (loc,style,suri,prefix)
426     | [ IDENT "hint" ] -> GrafiteAst.Hint loc
427     | [ IDENT "whelp"; "match" ] ; t = term -> 
428         GrafiteAst.WMatch (loc,t)
429     | [ IDENT "whelp"; IDENT "instance" ] ; t = term -> 
430         GrafiteAst.WInstance (loc,t)
431     | [ IDENT "whelp"; IDENT "locate" ] ; id = QSTRING -> 
432         GrafiteAst.WLocate (loc,id)
433     | [ IDENT "whelp"; IDENT "elim" ] ; t = term ->
434         GrafiteAst.WElim (loc, t)
435     | [ IDENT "whelp"; IDENT "hint" ] ; t = term -> 
436         GrafiteAst.WHint (loc,t)
437     ]
438   ];
439   alias_spec: [
440     [ IDENT "id"; id = QSTRING; SYMBOL "="; uri = QSTRING ->
441       let alpha = "[a-zA-Z]" in
442       let num = "[0-9]+" in
443       let ident_cont = "\\("^alpha^"\\|"^num^"\\|_\\|\\\\\\)" in
444       let ident = "\\("^alpha^ident_cont^"*\\|_"^ident_cont^"+\\)" in
445       let rex = Str.regexp ("^"^ident^"$") in
446       if Str.string_match rex id 0 then
447         if (try ignore (UriManager.uri_of_string uri); true
448             with UriManager.IllFormedUri _ -> false)
449         then
450           LexiconAst.Ident_alias (id, uri)
451         else 
452           raise
453            (HExtlib.Localized (loc, CicNotationParser.Parse_error (sprintf "Not a valid uri: %s" uri)))
454       else
455         raise (HExtlib.Localized (loc, CicNotationParser.Parse_error (
456           sprintf "Not a valid identifier: %s" id)))
457     | IDENT "symbol"; symbol = QSTRING;
458       instance = OPT [ LPAREN; IDENT "instance"; n = int; RPAREN -> n ];
459       SYMBOL "="; dsc = QSTRING ->
460         let instance =
461           match instance with Some i -> i | None -> 0
462         in
463         LexiconAst.Symbol_alias (symbol, instance, dsc)
464     | IDENT "num";
465       instance = OPT [ LPAREN; IDENT "instance"; n = int; RPAREN -> n ];
466       SYMBOL "="; dsc = QSTRING ->
467         let instance =
468           match instance with Some i -> i | None -> 0
469         in
470         LexiconAst.Number_alias (instance, dsc)
471     ]
472   ];
473   argument: [
474     [ l = LIST0 [ SYMBOL <:unicode<eta>> (* η *); SYMBOL "." -> () ];
475       id = IDENT ->
476         Ast.IdentArg (List.length l, id)
477     ]
478   ];
479   associativity: [
480     [ IDENT "left";  IDENT "associative" -> Gramext.LeftA
481     | IDENT "right"; IDENT "associative" -> Gramext.RightA
482     | IDENT "non"; IDENT "associative" -> Gramext.NonA
483     ]
484   ];
485   precedence: [
486     [ "with"; IDENT "precedence"; n = NUMBER -> int_of_string n ]
487   ];
488   notation: [
489     [ dir = OPT direction; s = QSTRING;
490       assoc = OPT associativity; prec = OPT precedence;
491       IDENT "for";
492       p2 = 
493         [ blob = UNPARSED_AST ->
494             add_raw_attribute ~text:(sprintf "@{%s}" blob)
495               (CicNotationParser.parse_level2_ast
496                 (Ulexing.from_utf8_string blob))
497         | blob = UNPARSED_META ->
498             add_raw_attribute ~text:(sprintf "${%s}" blob)
499               (CicNotationParser.parse_level2_meta
500                 (Ulexing.from_utf8_string blob))
501         ] ->
502           let assoc =
503             match assoc with
504             | None -> default_associativity
505             | Some assoc -> assoc
506           in
507           let prec =
508             match prec with
509             | None -> default_precedence
510             | Some prec -> prec
511           in
512           let p1 =
513             add_raw_attribute ~text:s
514               (CicNotationParser.parse_level1_pattern
515                 (Ulexing.from_utf8_string s))
516           in
517           (dir, p1, assoc, prec, p2)
518     ]
519   ];
520   level3_term: [
521     [ u = URI -> Ast.UriPattern (UriManager.uri_of_string u)
522     | id = IDENT -> Ast.VarPattern id
523     | SYMBOL "_" -> Ast.ImplicitPattern
524     | LPAREN; terms = LIST1 SELF; RPAREN ->
525         (match terms with
526         | [] -> assert false
527         | [term] -> term
528         | terms -> Ast.ApplPattern terms)
529     ]
530   ];
531   interpretation: [
532     [ s = CSYMBOL; args = LIST0 argument; SYMBOL "="; t = level3_term ->
533         (s, args, t)
534     ]
535   ];
536   
537   include_command: [ [
538       IDENT "include" ; path = QSTRING -> 
539         loc,path,LexiconAst.WithPreferences
540     | IDENT "include'" ; path = QSTRING -> 
541         loc,path,LexiconAst.WithoutPreferences
542    ]];
543
544   grafite_command: [ [
545       IDENT "set"; n = QSTRING; v = QSTRING ->
546         GrafiteAst.Set (loc, n, v)
547     | IDENT "drop" -> GrafiteAst.Drop loc
548     | IDENT "print"; s = IDENT -> GrafiteAst.Print (loc,s)
549     | IDENT "qed" -> GrafiteAst.Qed loc
550     | IDENT "variant" ; name = IDENT; SYMBOL ":"; 
551       typ = term; SYMBOL <:unicode<def>> ; newname = IDENT ->
552         GrafiteAst.Obj (loc, 
553           Ast.Theorem 
554             (`Variant,name,typ,Some (Ast.Ident (newname, None))))
555     | flavour = theorem_flavour; name = IDENT; SYMBOL ":"; typ = term;
556       body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
557         GrafiteAst.Obj (loc, Ast.Theorem (flavour, name, typ, body))
558     | flavour = theorem_flavour; name = IDENT; SYMBOL <:unicode<def>> (* ≝ *);
559       body = term ->
560         GrafiteAst.Obj (loc,
561           Ast.Theorem (flavour, name, Ast.Implicit, Some body))
562     | IDENT "axiom"; name = IDENT; SYMBOL ":"; typ = term ->
563         GrafiteAst.Obj (loc, Ast.Theorem (`Axiom, name, typ, None))
564     | "let"; ind_kind = [ "corec" -> `CoInductive | "rec"-> `Inductive ];
565         defs = CicNotationParser.let_defs -> 
566           let name,ty = 
567             match defs with
568             | (params,(Ast.Ident (name, None), Some ty),_,_) :: _ ->
569                 let ty =
570                  List.fold_right
571                   (fun var ty -> Ast.Binder (`Pi,var,ty)
572                   ) params ty
573                 in
574                  name,ty
575             | (_,(Ast.Ident (name, None), None),_,_) :: _ ->
576                 name, Ast.Implicit
577             | _ -> assert false 
578           in
579           let body = Ast.Ident (name,None) in
580           GrafiteAst.Obj (loc, Ast.Theorem(`Definition, name, ty,
581             Some (Ast.LetRec (ind_kind, defs, body))))
582     | IDENT "inductive"; spec = inductive_spec ->
583         let (params, ind_types) = spec in
584         GrafiteAst.Obj (loc, Ast.Inductive (params, ind_types))
585     | IDENT "coinductive"; spec = inductive_spec ->
586         let (params, ind_types) = spec in
587         let ind_types = (* set inductive flags to false (coinductive) *)
588           List.map (fun (name, _, term, ctors) -> (name, false, term, ctors))
589             ind_types
590         in
591         GrafiteAst.Obj (loc, Ast.Inductive (params, ind_types))
592     | IDENT "coercion" ; suri = URI ; arity = OPT int ->
593         let arity = match arity with None -> 0 | Some x -> x in
594         GrafiteAst.Coercion (loc, UriManager.uri_of_string suri, true, arity)
595     | IDENT "record" ; (params,name,ty,fields) = record_spec ->
596         GrafiteAst.Obj (loc, Ast.Record (params,name,ty,fields))
597     | IDENT "default" ; what = QSTRING ; uris = LIST1 URI ->
598        let uris = List.map UriManager.uri_of_string uris in
599         GrafiteAst.Default (loc,what,uris)
600     | IDENT "relation" ; aeq = tactic_term ; "on" ; a = tactic_term ;
601       refl = OPT [ IDENT "reflexivity" ; IDENT "proved" ; IDENT "by" ;
602                    refl = tactic_term -> refl ] ;
603       sym = OPT [ IDENT "symmetry" ; IDENT "proved" ; IDENT "by" ;
604                    sym = tactic_term -> sym ] ;
605       trans = OPT [ IDENT "transitivity" ; IDENT "proved" ; IDENT "by" ;
606                    trans = tactic_term -> trans ] ;
607       "as" ; id = IDENT ->
608        GrafiteAst.Relation (loc,id,a,aeq,refl,sym,trans)
609   ]];
610   lexicon_command: [ [
611       IDENT "alias" ; spec = alias_spec ->
612         LexiconAst.Alias (loc, spec)
613     | IDENT "notation"; (dir, l1, assoc, prec, l2) = notation ->
614         LexiconAst.Notation (loc, dir, l1, assoc, prec, l2)
615     | IDENT "interpretation"; id = QSTRING;
616       (symbol, args, l3) = interpretation ->
617         LexiconAst.Interpretation (loc, id, (symbol, args), l3)
618   ]];
619   executable: [
620     [ cmd = grafite_command; SYMBOL "." -> GrafiteAst.Command (loc, cmd)
621     | tac = tactical; punct = punctuation_tactical ->
622         GrafiteAst.Tactical (loc, tac, Some punct)
623     | punct = punctuation_tactical -> GrafiteAst.Tactical (loc, punct, None)
624     | mac = macro; SYMBOL "." -> GrafiteAst.Macro (loc, mac)
625     ]
626   ];
627   comment: [
628     [ BEGINCOMMENT ; ex = executable ; ENDCOMMENT -> 
629        GrafiteAst.Code (loc, ex)
630     | str = NOTE -> 
631        GrafiteAst.Note (loc, str)
632     ]
633   ];
634   statement: [
635     [ ex = executable ->
636        fun ~include_paths status -> status,LSome(GrafiteAst.Executable (loc,ex))
637     | com = comment ->
638        fun ~include_paths status -> status,LSome (GrafiteAst.Comment (loc, com))
639     | (iloc,fname,mode) = include_command ; SYMBOL "."  ->
640        fun ~include_paths status ->
641         let buri, fullpath = 
642           DependenciesParser.baseuri_of_script ~include_paths fname 
643         in
644         let status =
645          LexiconEngine.eval_command status 
646            (LexiconAst.Include (iloc,buri,mode,fullpath))
647         in
648          status,
649           LSome
650           (GrafiteAst.Executable
651            (loc,GrafiteAst.Command
652             (loc,GrafiteAst.Include (iloc,buri))))
653     | scom = lexicon_command ; SYMBOL "." ->
654        fun ~include_paths status ->
655         let status = LexiconEngine.eval_command status scom in
656          status,LNone loc
657     | EOI -> raise End_of_file
658     ]
659   ];
660 END
661
662 let exc_located_wrapper f =
663   try
664     f ()
665   with
666   | Stdpp.Exc_located (_, End_of_file) -> raise End_of_file
667   | Stdpp.Exc_located (floc, Stream.Error msg) ->
668       raise (HExtlib.Localized (floc,CicNotationParser.Parse_error msg))
669   | Stdpp.Exc_located (floc, exn) ->
670       raise
671        (HExtlib.Localized (floc,CicNotationParser.Parse_error (Printexc.to_string exn)))
672
673 let parse_statement lexbuf =
674   exc_located_wrapper
675     (fun () -> (Grammar.Entry.parse statement (Obj.magic lexbuf)))