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