+ tactic_term: [ [ t = term -> t ] ];
+ ident_list0: [
+ [ PAREN "["; idents = LIST0 IDENT SEP SYMBOL ";"; PAREN "]" -> idents ]
+ ];
+ tactic_term_list1: [
+ [ tactic_terms = LIST1 tactic_term SEP SYMBOL "," -> tactic_terms ]
+ ];
+ reduction_kind: [
+ [ [ IDENT "reduce" ] -> `Reduce
+ | [ IDENT "simplify" ] -> `Simpl
+ | [ IDENT "whd" ] -> `Whd
+ | [ IDENT "normalize" ] -> `Normalize ]
+ ];
+ sequent_pattern_spec : [
+ [ hyp_paths =
+ LIST0
+ [ id = IDENT ;
+ path = OPT [SYMBOL ":" ; path = term -> path ] ->
+ (id,match path with Some p -> p | None -> CicAst.UserInput) ]
+ SEP SYMBOL ";";
+ goal_path = OPT [ SYMBOL <:unicode<vdash>>; term = term -> term ] ->
+ let goal_path =
+ match goal_path with
+ None -> CicAst.UserInput
+ | Some goal_path -> goal_path
+ in
+ hyp_paths,goal_path
+ ]
+ ];
+ pattern_spec: [
+ [ res = OPT [
+ "in";
+ wanted_and_sps =
+ [ "match" ; wanted = term ;
+ sps = OPT [ "in"; sps = sequent_pattern_spec -> sps ] ->
+ Some wanted,sps
+ | sps = sequent_pattern_spec ->
+ None,Some sps
+ ] ->
+ let wanted,hyp_paths,goal_path =
+ match wanted_and_sps with
+ wanted,None -> wanted, [], CicAst.UserInput
+ | wanted,Some (hyp_paths,goal_path) -> wanted,hyp_paths,goal_path
+ in
+ wanted, hyp_paths, goal_path ] ->
+ match res with
+ None -> None,[],CicAst.UserInput
+ | Some ps -> ps]
+ ];
+ direction: [
+ [ SYMBOL ">" -> `LeftToRight
+ | SYMBOL "<" -> `RightToLeft ]
+ ];
+ tactic: [
+ [ IDENT "absurd"; t = tactic_term ->
+ TacticAst.Absurd (loc, t)
+ | IDENT "apply"; t = tactic_term ->
+ TacticAst.Apply (loc, t)
+ | IDENT "assumption" ->
+ TacticAst.Assumption loc
+ | IDENT "auto";
+ depth = OPT [ IDENT "depth"; SYMBOL "="; i = NUM -> int_of_string i ];
+ width = OPT [ IDENT "width"; SYMBOL "="; i = NUM -> int_of_string i ] ->
+ TacticAst.Auto (loc,depth,width)
+ | IDENT "clear"; id = IDENT ->
+ TacticAst.Clear (loc,id)
+ | IDENT "clearbody"; id = IDENT ->
+ TacticAst.ClearBody (loc,id)
+ | IDENT "change"; what = pattern_spec; "with"; t = tactic_term ->
+ TacticAst.Change (loc, what, t)
+ | IDENT "compare"; t = tactic_term ->
+ TacticAst.Compare (loc,t)
+ | IDENT "constructor"; n = NUM ->
+ TacticAst.Constructor (loc,int_of_string n)
+ | IDENT "contradiction" ->
+ TacticAst.Contradiction loc
+ | IDENT "cut"; t = tactic_term; ident = OPT [ "as"; id = IDENT -> id] ->
+ TacticAst.Cut (loc, ident, t)
+ | IDENT "decide"; IDENT "equality" ->
+ TacticAst.DecideEquality loc
+ | IDENT "decompose"; where = tactic_term ->
+ TacticAst.Decompose (loc, where)
+ | IDENT "discriminate"; t = tactic_term ->
+ TacticAst.Discriminate (loc, t)
+ | IDENT "elim"; what = tactic_term;
+ using = OPT [ "using"; using = tactic_term -> using ];
+ OPT "names"; num = OPT [num = int -> num]; idents = OPT ident_list0 ->
+ let idents = match idents with None -> [] | Some idents -> idents in
+ TacticAst.Elim (loc, what, using, num, idents)
+ | IDENT "elimType"; what = tactic_term;
+ using = OPT [ "using"; using = tactic_term -> using ];
+ OPT "names"; num = OPT [num = int -> num]; idents = OPT ident_list0 ->
+ let idents = match idents with None -> [] | Some idents -> idents in
+ TacticAst.ElimType (loc, what, using, num, idents)
+ | IDENT "exact"; t = tactic_term ->
+ TacticAst.Exact (loc, t)
+ | IDENT "exists" ->
+ TacticAst.Exists loc
+ | IDENT "fail" -> TacticAst.Fail loc
+ | IDENT "fold"; kind = reduction_kind; t = tactic_term; p = pattern_spec ->
+ let (pt,_,_) = p in
+ if pt <> None then
+ raise
+ (Parse_error
+ (loc,"the pattern cannot specify the term to replace, only its paths in the hypotheses and in the conclusion"))
+ else
+ TacticAst.Fold (loc, kind, t, p)
+ | IDENT "fourier" ->
+ TacticAst.Fourier loc
+ | IDENT "fwd"; hyp = IDENT; idents = OPT ident_list0 ->
+ let idents = match idents with None -> [] | Some idents -> idents in
+ TacticAst.FwdSimpl (loc, hyp, idents)
+ | IDENT "generalize"; p=pattern_spec; id = OPT ["as" ; id = IDENT -> id] ->
+ TacticAst.Generalize (loc,p,id)
+ | IDENT "goal"; n = NUM ->
+ TacticAst.Goal (loc, int_of_string n)
+ | IDENT "id" -> TacticAst.IdTac loc
+ | IDENT "injection"; t = tactic_term ->
+ TacticAst.Injection (loc, t)
+ | IDENT "intro"; ident = OPT IDENT ->
+ let idents = match ident with None -> [] | Some id -> [id] in
+ TacticAst.Intros (loc, Some 1, idents)
+ | IDENT "intros"; num = OPT [num = int -> num]; idents = OPT ident_list0 ->
+ let idents = match idents with None -> [] | Some idents -> idents in
+ TacticAst.Intros (loc, num, idents)
+ | IDENT "lapply";
+ depth = OPT [ IDENT "depth"; SYMBOL "="; i = NUM -> int_of_string i ];
+ what = tactic_term;
+ to_what = OPT [ "to" ; t = tactic_term_list1 -> t ];
+ ident = OPT [ "using" ; ident = IDENT -> ident ] ->
+ let to_what = match to_what with None -> [] | Some to_what -> to_what in
+ TacticAst.LApply (loc, depth, to_what, what, ident)
+ | IDENT "left" -> TacticAst.Left loc
+ | IDENT "letin"; where = IDENT ; SYMBOL <:unicode<def>> ; t = tactic_term ->
+ TacticAst.LetIn (loc, t, where)
+ | kind = reduction_kind; p = pattern_spec ->
+ TacticAst.Reduce (loc, kind, p)
+ | IDENT "reflexivity" ->
+ TacticAst.Reflexivity loc
+ | IDENT "replace"; p = pattern_spec; "with"; t = tactic_term ->
+ TacticAst.Replace (loc, p, t)
+ | IDENT "rewrite" ; d = direction; t = tactic_term ; p = pattern_spec ->
+ let (pt,_,_) = p in
+ if pt <> None then
+ raise
+ (Parse_error
+ (loc,"the pattern cannot specify the term to rewrite, only its paths in the hypotheses and in the conclusion"))
+ else
+ TacticAst.Rewrite (loc, d, t, p)
+ | IDENT "right" ->
+ TacticAst.Right loc
+ | IDENT "ring" ->
+ TacticAst.Ring loc
+ | IDENT "split" ->
+ TacticAst.Split loc
+ | IDENT "symmetry" ->
+ TacticAst.Symmetry loc
+ | IDENT "transitivity"; t = tactic_term ->
+ TacticAst.Transitivity (loc, t)
+ ]
+ ];
+ tactical:
+ [ "sequence" LEFTA
+ [ tacticals = LIST1 NEXT SEP SYMBOL ";" ->
+ match tacticals with
+ [] -> assert false
+ | [tac] -> tac
+ | l -> TacticAst.Seq (loc, l)
+ ]
+ | "then" NONA
+ [ tac = tactical; SYMBOL ";";
+ PAREN "["; tacs = LIST0 tactical SEP SYMBOL "|"; PAREN "]" ->
+ (TacticAst.Then (loc, tac, tacs))
+ ]
+ | "loops" RIGHTA
+ [ IDENT "do"; count = int; tac = tactical ->
+ TacticAst.Do (loc, count, tac)
+ | IDENT "repeat"; tac = tactical ->
+ TacticAst.Repeat (loc, tac)
+ ]
+ | "simple" NONA
+ [ IDENT "first";
+ PAREN "["; tacs = LIST0 tactical SEP SYMBOL "|"; PAREN "]" ->
+ TacticAst.First (loc, tacs)
+ | IDENT "try"; tac = NEXT ->
+ TacticAst.Try (loc, tac)
+ | IDENT "solve";
+ PAREN "["; tacs = LIST0 tactical SEP SYMBOL "|"; PAREN "]" ->
+ TacticAst.Solve (loc, tacs)
+ | PAREN "("; tac = tactical; PAREN ")" -> tac
+ | tac = tactic -> TacticAst.Tactic (loc, tac)
+ ]
+ ];
+ theorem_flavour: [
+ [ [ IDENT "definition" ] -> `Definition
+ | [ IDENT "fact" ] -> `Fact
+ | [ IDENT "lemma" ] -> `Lemma
+ | [ IDENT "remark" ] -> `Remark
+ | [ IDENT "theorem" ] -> `Theorem
+ ]
+ ];
+ inductive_spec: [ [
+ fst_name = IDENT; params = LIST0 [ arg=arg -> arg ];
+ SYMBOL ":"; fst_typ = term; SYMBOL <:unicode<def>>; OPT SYMBOL "|";
+ fst_constructors = LIST0 constructor SEP SYMBOL "|";
+ tl = OPT [ "with";
+ types = LIST1 [
+ name = IDENT; SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>;
+ OPT SYMBOL "|"; constructors = LIST0 constructor SEP SYMBOL "|" ->
+ (name, true, typ, constructors) ] SEP "with" -> types
+ ] ->
+ let params =
+ List.fold_right
+ (fun (names, typ) acc ->
+ (List.map (fun name -> (name, typ)) names) @ acc)
+ params []
+ in
+ let fst_ind_type = (fst_name, true, fst_typ, fst_constructors) in
+ let tl_ind_types = match tl with None -> [] | Some types -> types in
+ let ind_types = fst_ind_type :: tl_ind_types in
+ (params, ind_types)
+ ] ];
+
+ record_spec: [ [
+ name = IDENT; params = LIST0 [ arg = arg -> arg ] ;
+ SYMBOL ":"; typ = term; SYMBOL <:unicode<def>>; PAREN "{" ;
+ fields = LIST0 [
+ name = IDENT ; SYMBOL ":" ; ty = term -> (name,ty)
+ ] SEP SYMBOL ";"; PAREN "}" ->
+ let params =
+ List.fold_right
+ (fun (names, typ) acc ->
+ (List.map (fun name -> (name, typ)) names) @ acc)
+ params []
+ in
+ (params,name,typ,fields)
+ ] ];
+
+ macro: [
+ [ [ IDENT "quit" ] -> TacticAst.Quit loc
+(* | [ IDENT "abort" ] -> TacticAst.Abort loc *)
+ | [ IDENT "print" ]; name = QSTRING -> TacticAst.Print (loc, name)
+(* | [ IDENT "undo" ]; steps = OPT NUM ->
+ TacticAst.Undo (loc, int_opt steps)
+ | [ IDENT "redo" ]; steps = OPT NUM ->
+ TacticAst.Redo (loc, int_opt steps) *)
+ | [ IDENT "check" ]; t = term ->
+ TacticAst.Check (loc, t)
+ | [ IDENT "hint" ] -> TacticAst.Hint loc
+ | [ IDENT "whelp"; "match" ] ; t = term ->
+ TacticAst.WMatch (loc,t)
+ | [ IDENT "whelp"; IDENT "instance" ] ; t = term ->
+ TacticAst.WInstance (loc,t)
+ | [ IDENT "whelp"; IDENT "locate" ] ; id = IDENT ->
+ TacticAst.WLocate (loc,id)
+ | [ IDENT "whelp"; IDENT "elim" ] ; t = term ->
+ TacticAst.WElim (loc, t)
+ | [ IDENT "whelp"; IDENT "hint" ] ; t = term ->
+ TacticAst.WHint (loc,t)
+ | [ IDENT "print" ]; name = QSTRING -> TacticAst.Print (loc, name)
+ ]
+ ];
+
+ alias_spec: [
+ [ IDENT "id"; id = QSTRING; SYMBOL "="; uri = QSTRING ->
+ let alpha = "[a-zA-Z]" in
+ let num = "[0-9]+" in
+ let ident_cont = "\\("^alpha^"\\|"^num^"\\|_\\|\\\\\\)" in
+ let ident = "\\("^alpha^ident_cont^"*\\|_"^ident_cont^"+\\)" in
+ let rex = Str.regexp ("^"^ident^"$") in
+ if Str.string_match rex id 0 then
+ if (try ignore (UriManager.uri_of_string uri); true
+ with UriManager.IllFormedUri _ -> false)
+ then
+ TacticAst.Ident_alias (id, uri)
+ else
+ raise (Parse_error (loc,sprintf "Not a valid uri: %s" uri))
+ else
+ raise (Parse_error (loc,sprintf "Not a valid identifier: %s" id))
+ | IDENT "symbol"; symbol = QSTRING;
+ instance = OPT [ PAREN "("; IDENT "instance"; n = NUM; PAREN ")" -> n ];
+ SYMBOL "="; dsc = QSTRING ->
+ let instance =
+ match instance with Some i -> int_of_string i | None -> 0
+ in
+ TacticAst.Symbol_alias (symbol, instance, dsc)
+ | IDENT "num";
+ instance = OPT [ PAREN "("; IDENT "instance"; n = NUM; PAREN ")" -> n ];
+ SYMBOL "="; dsc = QSTRING ->
+ let instance =
+ match instance with Some i -> int_of_string i | None -> 0
+ in
+ TacticAst.Number_alias (instance, dsc)
+ ]
+ ];
+
+ command: [[
+ [ IDENT "set" ]; n = QSTRING; v = QSTRING ->
+ TacticAst.Set (loc, n, v)
+ | [ IDENT "drop" ] -> TacticAst.Drop loc
+ | [ IDENT "qed" ] -> TacticAst.Qed loc
+ | flavour = theorem_flavour; name = IDENT; SYMBOL ":"; typ = term;
+ body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
+ TacticAst.Obj (loc,TacticAst.Theorem (flavour, name, typ, body))
+ | flavour = theorem_flavour; name = IDENT;
+ body = OPT [ SYMBOL <:unicode<def>> (* ≝ *); body = term -> body ] ->
+ TacticAst.Obj (loc,TacticAst.Theorem (flavour, name, CicAst.Implicit, body))
+ | "let"; ind_kind = [ "corec" -> `CoInductive | "rec"-> `Inductive ];
+ defs = let_defs ->
+ let name,ty =
+ match defs with
+ | ((Cic.Name name,Some ty),_,_) :: _ -> name,ty
+ | ((Cic.Name name,None),_,_) :: _ -> name,CicAst.Implicit
+ | _ -> assert false
+ in
+ let body = CicAst.Ident (name,None) in
+ TacticAst.Obj (loc,TacticAst.Theorem(`Definition, name, ty,
+ Some (CicAst.LetRec (ind_kind, defs, body))))
+
+ | [ IDENT "inductive" ]; spec = inductive_spec ->
+ let (params, ind_types) = spec in
+ TacticAst.Obj (loc,TacticAst.Inductive (params, ind_types))
+ | [ IDENT "coinductive" ]; spec = inductive_spec ->
+ let (params, ind_types) = spec in
+ let ind_types = (* set inductive flags to false (coinductive) *)
+ List.map (fun (name, _, term, ctors) -> (name, false, term, ctors))
+ ind_types
+ in
+ TacticAst.Obj (loc,TacticAst.Inductive (params, ind_types))
+ | IDENT "coercion" ; name = IDENT ->
+ TacticAst.Coercion (loc, CicAst.Ident (name,Some []))
+ | IDENT "coercion" ; name = URI ->
+ TacticAst.Coercion (loc, CicAst.Uri (name,Some []))
+ | IDENT "alias" ; spec = alias_spec ->
+ TacticAst.Alias (loc, spec)
+ | IDENT "record" ; (params,name,ty,fields) = record_spec ->
+ TacticAst.Obj (loc,TacticAst.Record (params,name,ty,fields))
+ | IDENT "include" ; path = QSTRING ->
+ TacticAst.Include (loc,path)
+ | IDENT "default" ; what = QSTRING ; uris = LIST1 URI ->
+ let uris = List.map UriManager.uri_of_string uris in
+ TacticAst.Default (loc,what,uris)
+ ]];
+
+ executable: [
+ [ cmd = command; SYMBOL "." -> TacticAst.Command (loc, cmd)
+ | tac = tactical; SYMBOL "." -> TacticAst.Tactical (loc, tac)
+ | mac = macro; SYMBOL "." -> TacticAst.Macro (loc, mac)
+ ]
+ ];
+
+ comment: [
+ [ BEGINCOMMENT ; ex = executable ; ENDCOMMENT ->
+ TacticAst.Code (loc, ex)
+ | str = NOTE ->
+ TacticAst.Note (loc, str)
+ ]
+ ];
+
+ statement: [
+ [ ex = executable -> TacticAst.Executable (loc,ex)
+ | com = comment -> TacticAst.Comment (loc, com)
+ ]
+ ];
+ statements: [
+ [ l = LIST0 statement ; EOI -> l
+ ]
+ ];