1 (* Copyright (C) 2005, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://helm.cs.unibo.it/
28 module N = CicNotationPt
31 module LE = LexiconEngine
33 exception NoInclusionPerformed of string (* full path *)
35 type 'a localized_option =
40 (N.term, N.term, N.term G.reduction, N.term N.obj, string) G.statement
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
48 type 'status parser_status = {
50 term : N.term Grammar.Entry.e;
51 statement : #LE.status as 'status statement Grammar.Entry.e;
54 let grafite_callback = ref (fun _ -> ())
55 let set_grafite_callback cb = grafite_callback := cb
57 let lexicon_callback = ref (fun _ -> ())
58 let set_lexicon_callback cb = lexicon_callback := cb
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 }
67 let grafite_parser = ref (initial_parser ())
69 let add_raw_attribute ~text t = N.AttributedTerm (`Raw text, t)
71 let default_associativity = Gramext.NonA
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. *)
81 | (params,(N.Ident (name, None), ty),_,_) :: _ ->
82 let ty = match ty with Some ty -> ty | None -> N.Implicit `JustOne in
85 (fun var ty -> N.Binder (`Pi,var,ty)
91 let body = N.Ident (name,None) in
93 if List.length defs = 1 then
98 (loc, N.Theorem(flavour, name, ty, Some (N.LetRec (ind_kind, defs, body))))
100 let nmk_rec_corec ind_kind defs loc =
101 let loc,t = mk_rec_corec ind_kind defs loc in
104 let mk_rec_corec ind_kind defs loc =
105 let loc,t = mk_rec_corec ind_kind defs loc in
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
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)
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
132 type by_continuation =
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
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
145 GLOBAL: term statement;
146 constructor: [ [ name = IDENT; SYMBOL ":"; typ = term -> (name, typ) ] ];
147 tactic_term: [ [ t = term LEVEL "90" -> t ] ];
150 | id = IDENT -> Some id ]
152 ident_list0: [ [ LPAREN; idents = LIST0 new_name; RPAREN -> idents ] ];
154 [ tactic_terms = LIST1 tactic_term SEP SYMBOL "," -> tactic_terms ]
157 [ IDENT "normalize" -> `Normalize
158 | IDENT "simplify" -> `Simpl
159 | IDENT "unfold"; t = OPT tactic_term -> `Unfold t
160 | IDENT "whd" -> `Whd ]
163 [ IDENT "nnormalize" ; delta = OPT [ IDENT "nodelta" -> () ] ->
164 let delta = match delta with None -> true | _ -> false in
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
171 sequent_pattern_spec: [
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 ] ->
179 match goal_path, hyp_paths with
180 None, [] -> Some N.UserInput
182 | Some goal_path, _ -> Some goal_path
191 [ "match" ; wanted = tactic_term ;
192 sps = OPT [ "in"; sps = sequent_pattern_spec -> sps ] ->
194 | sps = sequent_pattern_spec ->
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
202 wanted, hyp_paths, goal_path ] ->
204 None -> None,[],Some N.UserInput
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]
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)) ]
222 [ SYMBOL ">" -> `LeftToRight
223 | SYMBOL "<" -> `RightToLeft ]
225 int: [ [ num = NUMBER -> int_of_string num ] ];
227 [ idents = OPT ident_list0 ->
228 match idents with None -> [] | Some idents -> idents
232 [ OPT [ IDENT "names" ];
233 num = OPT [ num = int -> num ];
234 idents = intros_names ->
238 using: [ [ using = OPT [ IDENT "using"; t = tactic_term -> t ] -> using ] ];
240 [ IDENT "napply"; t = tactic_term -> G.NApply (loc, t)
244 [ id = IDENT ; SYMBOL ":" ; ty = tactic_term -> id,`Decl ty
245 | id = IDENT ; SYMBOL ":" ; ty = tactic_term ;
246 SYMBOL <:unicode<def>> ; bo = tactic_term ->
248 SYMBOL <:unicode<vdash>>;
249 concl = tactic_term -> (List.rev hyps,concl) ] ->
250 G.NAssert (loc, seqs)
251 | IDENT "nauto"; params = auto_params -> G.NAuto (loc, params)
252 | IDENT "ncases"; what = tactic_term ; where = pattern_spec ->
253 G.NCases (loc, what, where)
254 | IDENT "nchange"; what = pattern_spec; "with"; with_what = tactic_term ->
255 G.NChange (loc, what, with_what)
256 | SYMBOL "@"; num = OPT NUMBER ->
258 match num with None -> None | Some x -> Some (int_of_string x))
259 | IDENT "nelim"; what = tactic_term ; where = pattern_spec ->
260 G.NElim (loc, what, where)
261 | IDENT "ngeneralize"; p=pattern_spec ->
262 G.NGeneralize (loc, p)
263 | IDENT "nletin"; name = IDENT ; SYMBOL <:unicode<def>> ; t = tactic_term;
264 where = pattern_spec ->
265 G.NLetIn (loc,where,t,name)
266 | kind = nreduction_kind; p = pattern_spec ->
267 G.NReduce (loc, kind, p)
268 | IDENT "nrewrite"; dir = direction; what = tactic_term ; where = pattern_spec ->
269 G.NRewrite (loc, dir, what, where)
270 | IDENT "ntry"; tac = SELF -> G.NTry (loc,tac)
271 | IDENT "nrepeat"; tac = SELF -> G.NRepeat (loc,tac)
272 | LPAREN; l = LIST1 SELF; RPAREN -> G.NBlock (loc,l)
273 | IDENT "nassumption" -> G.NAssumption loc
274 | SYMBOL "#"; n=IDENT -> G.NIntro (loc,n)
275 | SYMBOL "#"; SYMBOL "_" -> G.NIntro (loc,"_")
276 | SYMBOL "*" -> G.NCase1 (loc,"_")
277 | SYMBOL "*"; n=IDENT ->
282 [ IDENT "absurd"; t = tactic_term ->
284 | IDENT "apply"; IDENT "rule"; t = tactic_term ->
286 | IDENT "apply"; t = tactic_term ->
288 | IDENT "applyP"; t = tactic_term ->
290 | IDENT "applyS"; t = tactic_term ; params = auto_params ->
291 G.ApplyS (loc, t, params)
292 | IDENT "assumption" ->
294 | IDENT "autobatch"; params = auto_params ->
295 G.AutoBatch (loc,params)
296 | IDENT "cases"; what = tactic_term;
297 pattern = OPT pattern_spec;
298 specs = intros_spec ->
299 let pattern = match pattern with
300 | None -> None, [], Some N.UserInput
301 | Some pattern -> pattern
303 G.Cases (loc, what, pattern, specs)
304 | IDENT "clear"; ids = LIST1 IDENT ->
306 | IDENT "clearbody"; id = IDENT ->
308 | IDENT "change"; what = pattern_spec; "with"; t = tactic_term ->
309 G.Change (loc, what, t)
310 | IDENT "compose"; times = OPT int; t1 = tactic_term; t2 =
311 OPT [ "with"; t = tactic_term -> t ]; specs = intros_spec ->
312 let times = match times with None -> 1 | Some i -> i in
313 G.Compose (loc, t1, t2, times, specs)
314 | IDENT "constructor"; n = int ->
315 G.Constructor (loc, n)
316 | IDENT "contradiction" ->
318 | IDENT "cut"; t = tactic_term; ident = OPT [ "as"; id = IDENT -> id] ->
319 G.Cut (loc, ident, t)
320 | IDENT "decompose"; idents = OPT [ "as"; idents = LIST1 new_name -> idents ] ->
321 let idents = match idents with None -> [] | Some idents -> idents in
322 G.Decompose (loc, idents)
323 | IDENT "demodulate"; p = auto_params -> G.Demodulate (loc, p)
324 | IDENT "destruct"; xts = OPT [ ts = tactic_term_list1 -> ts ] ->
325 G.Destruct (loc, xts)
326 | IDENT "elim"; what = tactic_term; using = using;
327 pattern = OPT pattern_spec;
328 ispecs = intros_spec ->
329 let pattern = match pattern with
330 | None -> None, [], Some N.UserInput
331 | Some pattern -> pattern
333 G.Elim (loc, what, using, pattern, ispecs)
334 | IDENT "elimType"; what = tactic_term; using = using;
335 (num, idents) = intros_spec ->
336 G.ElimType (loc, what, using, (num, idents))
337 | IDENT "exact"; t = tactic_term ->
341 | IDENT "fail" -> G.Fail loc
342 | IDENT "fold"; kind = reduction_kind; t = tactic_term; p = pattern_spec ->
345 raise (HExtlib.Localized (loc, CicNotationParser.Parse_error
346 ("the pattern cannot specify the term to replace, only its"
347 ^ " paths in the hypotheses and in the conclusion")))
349 G.Fold (loc, kind, t, p)
352 | IDENT "fwd"; hyp = IDENT; idents = OPT [ "as"; idents = LIST1 new_name -> idents ] ->
353 let idents = match idents with None -> [] | Some idents -> idents in
354 G.FwdSimpl (loc, hyp, idents)
355 | IDENT "generalize"; p=pattern_spec; id = OPT ["as" ; id = IDENT -> id] ->
356 G.Generalize (loc,p,id)
357 | IDENT "id" -> G.IdTac loc
358 | IDENT "intro"; ident = OPT IDENT ->
359 let idents = match ident with None -> [] | Some id -> [Some id] in
360 G.Intros (loc, (Some 1, idents))
361 | IDENT "intros"; specs = intros_spec ->
362 G.Intros (loc, specs)
363 | IDENT "inversion"; t = tactic_term ->
366 linear = OPT [ IDENT "linear" ];
367 depth = OPT [ IDENT "depth"; SYMBOL "="; i = int -> i ];
369 to_what = OPT [ "to" ; t = tactic_term_list1 -> t ];
370 ident = OPT [ "as" ; ident = IDENT -> ident ] ->
371 let linear = match linear with None -> false | Some _ -> true in
372 let to_what = match to_what with None -> [] | Some to_what -> to_what in
373 G.LApply (loc, linear, depth, to_what, what, ident)
374 | IDENT "left" -> G.Left loc
375 | IDENT "letin"; where = IDENT ; SYMBOL <:unicode<def>> ; t = tactic_term ->
376 G.LetIn (loc, t, where)
377 | kind = reduction_kind; p = pattern_spec ->
378 G.Reduce (loc, kind, p)
379 | IDENT "reflexivity" ->
381 | IDENT "replace"; p = pattern_spec; "with"; t = tactic_term ->
382 G.Replace (loc, p, t)
383 | IDENT "rewrite" ; d = direction; t = tactic_term ; p = pattern_spec;
384 xnames = OPT [ "as"; n = ident_list0 -> n ] ->
388 (HExtlib.Localized (loc,
389 (CicNotationParser.Parse_error
390 "the pattern cannot specify the term to rewrite, only its paths in the hypotheses and in the conclusion")))
392 let n = match xnames with None -> [] | Some names -> names in
393 G.Rewrite (loc, d, t, p, n)
400 | IDENT "symmetry" ->
402 | IDENT "transitivity"; t = tactic_term ->
403 G.Transitivity (loc, t)
404 (* Produzioni Aggiunte *)
405 | IDENT "assume" ; id = IDENT ; SYMBOL ":" ; t = tactic_term ->
406 G.Assume (loc, id, t)
407 | IDENT "suppose" ; t = tactic_term ; LPAREN ; id = IDENT ; RPAREN ;
408 t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ;
409 t' = tactic_term -> t']->
410 G.Suppose (loc, t, id, t1)
411 | "let" ; id1 = IDENT ; SYMBOL ":" ; t1 = tactic_term ;
412 IDENT "such" ; IDENT "that" ; t2=tactic_term ; LPAREN ;
413 id2 = IDENT ; RPAREN ->
414 G.ExistsElim (loc, `Auto ([],[]), id1, t1, id2, t2)
416 [ IDENT "using"; t=tactic_term -> `Term t
417 | params = auto_params -> `Auto params] ;
418 cont=by_continuation ->
420 BYC_done -> G.Bydone (loc, just)
421 | BYC_weproved (ty,id,t1) ->
422 G.By_just_we_proved(loc, just, ty, id, t1)
423 | BYC_letsuchthat (id1,t1,id2,t2) ->
424 G.ExistsElim (loc, just, id1, t1, id2, t2)
425 | BYC_wehaveand (id1,t1,id2,t2) ->
426 G.AndElim (loc, just, id1, t1, id2, t2))
427 | 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']->
428 G.We_need_to_prove (loc, t, id, t1)
429 | IDENT "we" ; IDENT "proceed" ; IDENT "by" ; IDENT "cases" ; "on" ; t=tactic_term ; "to" ; IDENT "prove" ; t1=tactic_term ->
430 G.We_proceed_by_cases_on (loc, t, t1)
431 | IDENT "we" ; IDENT "proceed" ; IDENT "by" ; IDENT "induction" ; "on" ; t=tactic_term ; "to" ; IDENT "prove" ; t1=tactic_term ->
432 G.We_proceed_by_induction_on (loc, t, t1)
433 | IDENT "by" ; IDENT "induction" ; IDENT "hypothesis" ; IDENT "we" ; IDENT "know" ; t=tactic_term ; LPAREN ; id = IDENT ; RPAREN ->
434 G.Byinduction(loc, t, id)
435 | IDENT "the" ; IDENT "thesis" ; IDENT "becomes" ; t=tactic_term ->
436 G.Thesisbecomes(loc, t)
437 | IDENT "case" ; id = IDENT ; params=LIST0[LPAREN ; i=IDENT ;
438 SYMBOL":" ; t=tactic_term ; RPAREN -> i,t] ->
439 G.Case(loc,id,params)
440 (* DO NOT FACTORIZE with the two following, camlp5 sucks*)
442 termine = tactic_term;
446 [ IDENT "using"; t=tactic_term -> `Term t
447 | IDENT "using"; IDENT "once"; term=tactic_term -> `SolveWith term
448 | IDENT "proof" -> `Proof
449 | params = auto_params -> `Auto params];
450 cont = rewriting_step_continuation ->
451 G.RewritingStep(loc, Some (None,termine), t1, t2, cont)
452 | IDENT "obtain" ; name = IDENT;
453 termine = tactic_term;
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 (Some name,termine), t1, t2, cont)
466 [ IDENT "using"; t=tactic_term -> `Term t
467 | IDENT "using"; IDENT "once"; term=tactic_term -> `SolveWith term
468 | IDENT "proof" -> `Proof
469 | params = auto_params -> `Auto params];
470 cont = rewriting_step_continuation ->
471 G.RewritingStep(loc, None, t1, t2, cont)
475 [ IDENT "paramodulation"
488 i = auto_fixed_param -> i,""
489 | i = auto_fixed_param ; SYMBOL "="; v = [ v = int ->
490 string_of_int v | v = IDENT -> v ] -> i,v ];
491 tl = OPT [ IDENT "by"; tl = tactic_term_list1 -> tl] ->
492 (match tl with Some l -> l | None -> []),
498 [ IDENT "prefix"; SYMBOL "="; prefix = QSTRING -> G.IPPrefix prefix
499 | flavour = inline_flavour -> G.IPAs flavour
500 | IDENT "coercions" -> G.IPCoercions
501 | IDENT "debug"; SYMBOL "="; debug = int -> G.IPDebug debug
502 | IDENT "procedural" -> G.IPProcedural
503 | IDENT "nodefaults" -> G.IPNoDefaults
504 | IDENT "depth"; SYMBOL "="; depth = int -> G.IPDepth depth
505 | IDENT "level"; SYMBOL "="; level = int -> G.IPLevel level
506 | IDENT "comments" -> G.IPComments
507 | IDENT "cr" -> G.IPCR
512 [ 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)
513 | WEPROVED; ty = tactic_term ; t1 = OPT [IDENT "that" ; IDENT "is" ; IDENT "equivalent" ; "to" ; t2 = tactic_term -> t2] ;
514 "done" -> BYC_weproved (ty,None,t1)
516 | "let" ; id1 = IDENT ; SYMBOL ":" ; t1 = tactic_term ;
517 IDENT "such" ; IDENT "that" ; t2=tactic_term ; LPAREN ;
518 id2 = IDENT ; RPAREN -> BYC_letsuchthat (id1,t1,id2,t2)
519 | WEHAVE; t1=tactic_term ; LPAREN ; id1=IDENT ; RPAREN ;"and" ; t2=tactic_term ; LPAREN ; id2=IDENT ; RPAREN ->
520 BYC_wehaveand (id1,t1,id2,t2)
523 rewriting_step_continuation : [
530 [ t1 = SELF; SYMBOL ";"; t2 = SELF ->
533 | G.Seq (_, l) -> l @ [ t2 ]
539 [ tac = SELF; SYMBOL ";";
540 SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
541 (G.Then (loc, tac, tacs))
544 [ IDENT "do"; count = int; tac = SELF ->
545 G.Do (loc, count, tac)
546 | IDENT "repeat"; tac = SELF -> G.Repeat (loc, tac)
550 SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
552 | IDENT "try"; tac = SELF -> G.Try (loc, tac)
554 SYMBOL "["; tacs = LIST0 SELF SEP SYMBOL "|"; SYMBOL "]"->
556 | IDENT "progress"; tac = SELF -> G.Progress (loc, tac)
557 | LPAREN; tac = SELF; RPAREN -> tac
558 | tac = tactic -> tac
561 npunctuation_tactical:
563 [ SYMBOL "[" -> G.NBranch loc
564 | SYMBOL "|" -> G.NShift loc
565 | i = LIST1 int SEP SYMBOL ","; SYMBOL ":" -> G.NPos (loc, i)
566 | SYMBOL "*"; SYMBOL ":" -> G.NWildcard loc
567 | SYMBOL "]" -> G.NMerge loc
568 | SYMBOL ";" -> G.NSemicolon loc
569 | SYMBOL "." -> G.NDot loc
572 punctuation_tactical:
574 [ SYMBOL "[" -> G.Branch loc
575 | SYMBOL "|" -> G.Shift loc
576 | i = LIST1 int SEP SYMBOL ","; SYMBOL ":" -> G.Pos (loc, i)
577 | SYMBOL "*"; SYMBOL ":" -> G.Wildcard loc
578 | SYMBOL "]" -> G.Merge loc
579 | SYMBOL ";" -> G.Semicolon loc
580 | SYMBOL "." -> G.Dot loc
583 non_punctuation_tactical:
585 [ IDENT "focus"; goals = LIST1 int -> G.Focus (loc, goals)
586 | IDENT "unfocus" -> G.Unfocus loc
587 | IDENT "skip" -> G.Skip loc
591 [ [ IDENT "ndefinition" ] -> `Definition
592 | [ IDENT "nfact" ] -> `Fact
593 | [ IDENT "nlemma" ] -> `Lemma
594 | [ IDENT "nremark" ] -> `Remark
595 | [ IDENT "ntheorem" ] -> `Theorem
599 [ [ IDENT "definition" ] -> `Definition
600 | [ IDENT "fact" ] -> `Fact
601 | [ IDENT "lemma" ] -> `Lemma
602 | [ IDENT "remark" ] -> `Remark
603 | [ IDENT "theorem" ] -> `Theorem
607 [ attr = theorem_flavour -> attr
608 | [ IDENT "axiom" ] -> `Axiom
609 | [ IDENT "variant" ] -> `Variant
614 params = LIST0 protected_binder_vars;
615 SYMBOL ":"; fst_typ = term; SYMBOL <:unicode<def>>; OPT SYMBOL "|";
616 fst_constructors = LIST0 constructor SEP SYMBOL "|";
619 name = IDENT; SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>;
620 OPT SYMBOL "|"; constructors = LIST0 constructor SEP SYMBOL "|" ->
621 (name, true, typ, constructors) ] SEP "with" -> types
625 (fun (names, typ) acc ->
626 (List.map (fun name -> (name, typ)) names) @ acc)
629 let fst_ind_type = (fst_name, true, fst_typ, fst_constructors) in
630 let tl_ind_types = match tl with None -> [] | Some types -> types in
631 let ind_types = fst_ind_type :: tl_ind_types in
637 params = LIST0 protected_binder_vars;
638 SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>; SYMBOL "{" ;
642 SYMBOL ":" -> false,0
643 | SYMBOL ":"; SYMBOL ">" -> true,0
644 | SYMBOL ":"; arity = int ; SYMBOL ">" -> true,arity
647 let b,n = coercion in
649 ] SEP SYMBOL ";"; SYMBOL "}" ->
652 (fun (names, typ) acc ->
653 (List.map (fun name -> (name, typ)) names) @ acc)
656 (params,name,typ,fields)
660 [ [ IDENT "ncheck" ]; t = term -> G.NCheck (loc,t)
665 [ [ IDENT "check" ]; t = term ->
667 | [ IDENT "eval" ]; kind = reduction_kind; "on"; t = tactic_term ->
668 G.Eval (loc, kind, t)
669 | IDENT "inline"; suri = QSTRING; params = inline_params ->
670 G.Inline (loc, suri, params)
671 | [ IDENT "hint" ]; rew = OPT (IDENT "rewrite") ->
672 if rew = None then G.Hint (loc, false) else G.Hint (loc,true)
673 | IDENT "auto"; params = auto_params ->
674 G.AutoInteractive (loc,params)
675 | [ IDENT "whelp"; "match" ] ; t = term ->
677 | [ IDENT "whelp"; IDENT "instance" ] ; t = term ->
679 | [ IDENT "whelp"; IDENT "locate" ] ; id = QSTRING ->
681 | [ IDENT "whelp"; IDENT "elim" ] ; t = term ->
683 | [ IDENT "whelp"; IDENT "hint" ] ; t = term ->
688 [ IDENT "id"; id = QSTRING; SYMBOL "="; uri = QSTRING ->
689 let alpha = "[a-zA-Z]" in
690 let num = "[0-9]+" in
691 let ident_cont = "\\("^alpha^"\\|"^num^"\\|_\\|\\\\\\)" in
692 let decoration = "\\'" in
693 let ident = "\\("^alpha^ident_cont^"*"^decoration^"*\\|_"^ident_cont^"+"^decoration^"*\\)" in
694 let rex = Str.regexp ("^"^ident^"$") in
695 if Str.string_match rex id 0 then
696 if (try ignore (UriManager.uri_of_string uri); true
697 with UriManager.IllFormedUri _ -> false) ||
698 (try ignore (NReference.reference_of_string uri); true
699 with NReference.IllFormedReference _ -> false)
701 L.Ident_alias (id, uri)
704 (HExtlib.Localized (loc, CicNotationParser.Parse_error (Printf.sprintf "Not a valid uri: %s" uri)))
706 raise (HExtlib.Localized (loc, CicNotationParser.Parse_error (
707 Printf.sprintf "Not a valid identifier: %s" id)))
708 | IDENT "symbol"; symbol = QSTRING;
709 instance = OPT [ LPAREN; IDENT "instance"; n = int; RPAREN -> n ];
710 SYMBOL "="; dsc = QSTRING ->
712 match instance with Some i -> i | None -> 0
714 L.Symbol_alias (symbol, instance, dsc)
716 instance = OPT [ LPAREN; IDENT "instance"; n = int; RPAREN -> n ];
717 SYMBOL "="; dsc = QSTRING ->
719 match instance with Some i -> i | None -> 0
721 L.Number_alias (instance, dsc)
725 [ l = LIST0 [ SYMBOL <:unicode<eta>> (* η *); SYMBOL "." -> () ];
727 N.IdentArg (List.length l, id)
731 [ IDENT "left"; IDENT "associative" -> Gramext.LeftA
732 | IDENT "right"; IDENT "associative" -> Gramext.RightA
733 | IDENT "non"; IDENT "associative" -> Gramext.NonA
737 [ "with"; IDENT "precedence"; n = NUMBER -> int_of_string n ]
740 [ dir = OPT direction; s = QSTRING;
741 assoc = OPT associativity; prec = precedence;
744 [ blob = UNPARSED_AST ->
745 add_raw_attribute ~text:(Printf.sprintf "@{%s}" blob)
746 (CicNotationParser.parse_level2_ast
747 (Ulexing.from_utf8_string blob))
748 | blob = UNPARSED_META ->
749 add_raw_attribute ~text:(Printf.sprintf "${%s}" blob)
750 (CicNotationParser.parse_level2_meta
751 (Ulexing.from_utf8_string blob))
755 | None -> default_associativity
756 | Some assoc -> assoc
759 add_raw_attribute ~text:s
760 (CicNotationParser.parse_level1_pattern prec
761 (Ulexing.from_utf8_string s))
763 (dir, p1, assoc, prec, p2)
767 [ u = URI -> N.UriPattern (UriManager.uri_of_string u)
768 | r = NREF -> N.NRefPattern (NReference.reference_of_string r)
769 | IMPLICIT -> N.ImplicitPattern
770 | id = IDENT -> N.VarPattern id
771 | LPAREN; terms = LIST1 SELF; RPAREN ->
775 | terms -> N.ApplPattern terms)
779 [ s = CSYMBOL; args = LIST0 argument; SYMBOL "="; t = level3_term ->
785 IDENT "include" ; path = QSTRING ->
786 loc,path,true,L.WithPreferences
787 | IDENT "include" ; IDENT "source" ; path = QSTRING ->
788 loc,path,false,L.WithPreferences
789 | IDENT "include'" ; path = QSTRING ->
790 loc,path,true,L.WithoutPreferences
793 grafite_ncommand: [ [
794 IDENT "nqed" -> G.NQed loc
795 | nflavour = ntheorem_flavour; name = IDENT; SYMBOL ":"; typ = term;
796 body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
797 G.NObj (loc, N.Theorem (nflavour, name, typ, body))
798 | nflavour = ntheorem_flavour; name = IDENT; SYMBOL <:unicode<def>> (* ≝ *);
800 G.NObj (loc, N.Theorem (nflavour, name, N.Implicit `JustOne, Some body))
801 | IDENT "naxiom"; name = IDENT; SYMBOL ":"; typ = term ->
802 G.NObj (loc, N.Theorem (`Axiom, name, typ, None))
803 | NLETCOREC ; defs = let_defs ->
804 nmk_rec_corec `CoInductive defs loc
805 | NLETREC ; defs = let_defs ->
806 nmk_rec_corec `Inductive defs loc
807 | IDENT "ninductive"; spec = inductive_spec ->
808 let (params, ind_types) = spec in
809 G.NObj (loc, N.Inductive (params, ind_types))
810 | IDENT "ncoinductive"; spec = inductive_spec ->
811 let (params, ind_types) = spec in
812 let ind_types = (* set inductive flags to false (coinductive) *)
813 List.map (fun (name, _, term, ctors) -> (name, false, term, ctors))
816 G.NObj (loc, N.Inductive (params, ind_types))
817 | IDENT "universe"; IDENT "constraint"; u1 = tactic_term;
818 strict = [ SYMBOL <:unicode<lt>> -> true
819 | SYMBOL <:unicode<leq>> -> false ];
823 | CicNotationPt.AttributedTerm (_, CicNotationPt.Sort (`NType i)) ->
824 NUri.uri_of_string ("cic:/matita/pts/Type"^i^".univ")
825 | CicNotationPt.AttributedTerm (_, CicNotationPt.Sort (`NCProp i)) ->
826 NUri.uri_of_string ("cic:/matita/pts/CProp"^i^".univ")
827 | _ -> raise (Failure "only a sort can be constrained")
831 | CicNotationPt.AttributedTerm (_, CicNotationPt.Sort (`NType i)) ->
832 NUri.uri_of_string ("cic:/matita/pts/Type"^i^".univ")
833 | CicNotationPt.AttributedTerm (_, CicNotationPt.Sort (`NCProp i)) ->
834 NUri.uri_of_string ("cic:/matita/pts/CProp"^i^".univ")
835 | _ -> raise (Failure "only a sort can be constrained")
837 G.NUnivConstraint (loc, strict,u1,u2)
838 | IDENT "unification"; IDENT "hint"; n = int; t = tactic_term ->
839 G.UnificationHint (loc, t, n)
840 | IDENT "ncoercion"; name = IDENT; SYMBOL ":"; ty = term;
841 SYMBOL <:unicode<def>>; t = term; "on";
842 id = [ IDENT | PIDENT ]; SYMBOL ":"; source = term;
843 "to"; target = term ->
844 G.NCoercion(loc,name,t,ty,(id,source),target)
845 | IDENT "nrecord" ; (params,name,ty,fields) = record_spec ->
846 G.NObj (loc, N.Record (params,name,ty,fields))
847 | IDENT "ncopy" ; s = IDENT; IDENT "from"; u = URI; "with";
848 m = LIST0 [ u1 = URI; SYMBOL <:unicode<mapsto>>; u2 = URI -> u1,u2 ] ->
849 G.NCopy (loc,s,NUri.uri_of_string u,
850 List.map (fun a,b -> NUri.uri_of_string a, NUri.uri_of_string b) m)
854 IDENT "set"; n = QSTRING; v = QSTRING ->
856 | IDENT "drop" -> G.Drop loc
857 | IDENT "print"; s = IDENT -> G.Print (loc,s)
858 | IDENT "qed" -> G.Qed loc
859 | IDENT "variant" ; name = IDENT; SYMBOL ":";
860 typ = term; SYMBOL <:unicode<def>> ; newname = IDENT ->
863 (`Variant,name,typ,Some (N.Ident (newname, None))))
864 | flavour = theorem_flavour; name = IDENT; SYMBOL ":"; typ = term;
865 body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
866 G.Obj (loc, N.Theorem (flavour, name, typ, body))
867 | flavour = theorem_flavour; name = IDENT; SYMBOL <:unicode<def>> (* ≝ *);
870 N.Theorem (flavour, name, N.Implicit `JustOne, Some body))
871 | IDENT "axiom"; name = IDENT; SYMBOL ":"; typ = term ->
872 G.Obj (loc, N.Theorem (`Axiom, name, typ, None))
873 | LETCOREC ; defs = let_defs ->
874 mk_rec_corec `CoInductive defs loc
875 | LETREC ; defs = let_defs ->
876 mk_rec_corec `Inductive defs loc
877 | IDENT "inductive"; spec = inductive_spec ->
878 let (params, ind_types) = spec in
879 G.Obj (loc, N.Inductive (params, ind_types))
880 | IDENT "coinductive"; spec = inductive_spec ->
881 let (params, ind_types) = spec in
882 let ind_types = (* set inductive flags to false (coinductive) *)
883 List.map (fun (name, _, term, ctors) -> (name, false, term, ctors))
886 G.Obj (loc, N.Inductive (params, ind_types))
888 t = [ u = URI -> N.Uri (u,None) | t = tactic_term ; OPT "with" -> t ] ;
889 arity = OPT int ; saturations = OPT int;
890 composites = OPT (IDENT "nocomposites") ->
891 let arity = match arity with None -> 0 | Some x -> x in
892 let saturations = match saturations with None -> 0 | Some x -> x in
893 let composites = match composites with None -> true | Some _ -> false in
895 (loc, t, composites, arity, saturations)
896 | IDENT "prefer" ; IDENT "coercion"; t = tactic_term ->
897 G.PreferCoercion (loc, t)
898 | IDENT "pump" ; steps = int ->
900 | IDENT "inverter"; name = IDENT; IDENT "for";
901 indty = tactic_term; paramspec = inverter_param_list ->
903 (loc, name, indty, paramspec)
904 | IDENT "record" ; (params,name,ty,fields) = record_spec ->
905 G.Obj (loc, N.Record (params,name,ty,fields))
906 | IDENT "default" ; what = QSTRING ; uris = LIST1 URI ->
907 let uris = List.map UriManager.uri_of_string uris in
908 G.Default (loc,what,uris)
909 | IDENT "relation" ; aeq = tactic_term ; "on" ; a = tactic_term ;
910 refl = OPT [ IDENT "reflexivity" ; IDENT "proved" ; IDENT "by" ;
911 refl = tactic_term -> refl ] ;
912 sym = OPT [ IDENT "symmetry" ; IDENT "proved" ; IDENT "by" ;
913 sym = tactic_term -> sym ] ;
914 trans = OPT [ IDENT "transitivity" ; IDENT "proved" ; IDENT "by" ;
915 trans = tactic_term -> trans ] ;
917 G.Relation (loc,id,a,aeq,refl,sym,trans)
920 IDENT "alias" ; spec = alias_spec ->
922 | IDENT "notation"; (dir, l1, assoc, prec, l2) = notation ->
923 L.Notation (loc, dir, l1, assoc, prec, l2)
924 | IDENT "interpretation"; id = QSTRING;
925 (symbol, args, l3) = interpretation ->
926 L.Interpretation (loc, id, (symbol, args), l3)
929 [ cmd = grafite_command; SYMBOL "." -> G.Command (loc, cmd)
930 | ncmd = grafite_ncommand; SYMBOL "." -> G.NCommand (loc, ncmd)
931 | tac = atomic_tactical LEVEL "loops"; punct = punctuation_tactical ->
932 G.Tactic (loc, Some tac, punct)
933 | punct = punctuation_tactical -> G.Tactic (loc, None, punct)
934 | tac = ntactic; SYMBOL "#" ; SYMBOL "#" ; punct = punctuation_tactical ->
935 G.NTactic (loc, [tac; npunct_of_punct punct])
936 | tac = ntactic; punct = punctuation_tactical ->
937 G.NTactic (loc, [tac; npunct_of_punct punct])
938 | SYMBOL "#" ; SYMBOL "#" ; punct = npunctuation_tactical ->
939 G.NTactic (loc, [punct])
940 | tac = non_punctuation_tactical; punct = punctuation_tactical ->
941 G.NonPunctuationTactical (loc, tac, punct)
942 | SYMBOL "#" ; SYMBOL "#" ; tac = non_punctuation_tactical;
943 SYMBOL "#" ; SYMBOL "#" ; punct = punctuation_tactical ->
944 G.NTactic (loc, [nnon_punct_of_punct tac; npunct_of_punct punct])
945 | SYMBOL "#" ; SYMBOL "#" ; tac = non_punctuation_tactical;
946 punct = punctuation_tactical ->
947 G.NTactic (loc, [nnon_punct_of_punct tac; npunct_of_punct punct])
948 | mac = macro; SYMBOL "." -> G.Macro (loc, mac)
949 | mac = nmacro; SYMBOL "." -> G.NMacro (loc, mac)
953 [ BEGINCOMMENT ; ex = executable ; ENDCOMMENT ->
961 fun ?(never_include=false) ~include_paths status ->
962 let stm = G.Executable (loc, ex) in
963 !grafite_callback stm;
966 fun ?(never_include=false) ~include_paths status ->
967 let stm = G.Comment (loc, com) in
968 !grafite_callback stm;
970 | (iloc,fname,normal,mode) = include_command ; SYMBOL "." ->
971 fun ?(never_include=false) ~include_paths status ->
972 let _root, buri, fullpath, _rrelpath =
973 Librarian.baseuri_of_script ~include_paths fname in
974 if never_include then raise (NoInclusionPerformed fullpath)
979 (loc, G.Command (loc, G.Include (iloc,normal,`OldAndNew,fname))) in
980 !grafite_callback stm;
982 LE.eval_command status (L.Include (iloc,buri,mode,fullpath)) in
985 (loc,G.Command (loc,G.Include (iloc,normal,`OldAndNew,buri)))
989 | scom = lexicon_command ; SYMBOL "." ->
990 fun ?(never_include=false) ~include_paths status ->
991 !lexicon_callback scom;
992 let status = LE.eval_command status scom in
994 | EOI -> raise End_of_file
1001 let _ = initialize_parser () ;;
1003 let exc_located_wrapper f =
1007 | Stdpp.Exc_located (_, End_of_file) -> raise End_of_file
1008 | Stdpp.Exc_located (floc, Stream.Error msg) ->
1009 raise (HExtlib.Localized (floc,CicNotationParser.Parse_error msg))
1010 | Stdpp.Exc_located (floc, HExtlib.Localized(_,exn)) ->
1012 (HExtlib.Localized (floc,CicNotationParser.Parse_error (Printexc.to_string exn)))
1013 | Stdpp.Exc_located (floc, exn) ->
1015 (HExtlib.Localized (floc,CicNotationParser.Parse_error (Printexc.to_string exn)))
1017 let parse_statement lexbuf =
1019 (fun () -> (Grammar.Entry.parse (Obj.magic !grafite_parser.statement) (Obj.magic lexbuf)))
1021 let statement () = Obj.magic !grafite_parser.statement
1023 let history = ref [] ;;
1026 LexiconSync.push ();
1027 history := !grafite_parser :: !history;
1028 grafite_parser := initial_parser ();
1029 initialize_parser ()
1035 | [] -> assert false
1037 grafite_parser := gp;
1041 (* vim:set foldmethod=marker: *)