diff options
Diffstat (limited to 'parsing/g_vernacnew.ml4')
-rw-r--r-- | parsing/g_vernacnew.ml4 | 817 |
1 files changed, 817 insertions, 0 deletions
diff --git a/parsing/g_vernacnew.ml4 b/parsing/g_vernacnew.ml4 new file mode 100644 index 000000000..e88e97141 --- /dev/null +++ b/parsing/g_vernacnew.ml4 @@ -0,0 +1,817 @@ +(***********************************************************************) +(* v * The Coq Proof Assistant / The Coq Development Team *) +(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *) +(* \VV/ *************************************************************) +(* // * This file is distributed under the terms of the *) +(* * GNU Lesser General Public License Version 2.1 *) +(***********************************************************************) + +(* $Id$ *) + +open Pp +open Util +open Names +open Coqast +open Topconstr +open Vernacexpr +open Pcoq +open Tactic +open Decl_kinds +open Genarg +open Extend +open Ppextend +open Goptions + +open Prim +open Constr +open Vernac_ +open Module + + +let vernac_kw = [ ";"; ","; ">->"; ":<"; "<:" ] +let _ = List.iter (fun s -> Lexer.add_token ("",s)) vernac_kw + +(* Rem: do not join the different GEXTEND into one, it breaks native *) +(* compilation on PowerPC and Sun architectures *) + +let check_command = Gram.Entry.create "vernac:check_command" +let class_rawexpr = Gram.Entry.create "vernac:class_rawexpr" +let thm_token = Gram.Entry.create "vernac:thm_token" +let def_body = Gram.Entry.create "vernac:def_body" + +GEXTEND Gram + GLOBAL: vernac gallina_ext; + vernac: + (* Better to parse ";" here: in case of failure (e.g. in coerce_to_var), *) + (* ";" is still in the stream and discard_to_dot works correctly *) + [ [ g = gallina; ";" -> g + | g = gallina_ext; ";" -> g + | c = command; ";" -> c + | c = syntax; ";" -> c + | "["; l = LIST1 located_vernac; "]"; ";" -> VernacList l + ] ] + ; + vernac: FIRST + [ [ IDENT "Time"; v = vernac -> VernacTime v ] ] + ; + vernac: LAST + [ [ gln = OPT[n=natural; ":" -> n]; + tac = subgoal_command; ";" -> tac gln ] ] + ; + subgoal_command: + [ [ c = check_command -> c + | d = use_default_tac; tac = Tactic.tactic -> + (fun g -> + let g = match g with Some gl -> gl | _ -> 1 in + VernacSolve(g,tac,d)) ] ] + ; + located_vernac: + [ [ v = vernac -> loc, v ] ] + ; + use_default_tac: + [ [ "!!" -> false + | -> true ] ] + ; +END + + +let test_plurial_form = function + | [_] -> + Options.if_verbose warning + "Keywords Variables/Hypotheses/Parameters expect more than one assumption" + | _ -> () + +let no_coercion loc (c,x) = + if c then Util.user_err_loc + (loc,"no_coercion",Pp.str"no coercion allowed here"); + x + +(* Gallina declarations *) +GEXTEND Gram + GLOBAL: gallina gallina_ext thm_token def_body; + + gallina: + (* Definition, Theorem, Variable, Axiom, ... *) + [ [ thm = thm_token; id = base_ident; bl = LIST0 binder; ":"; + c = lconstr -> + VernacStartTheoremProof (thm, id, (bl, c), false, (fun _ _ -> ())) + | (f,d,e) = def_token; id = base_ident; b = def_body -> + VernacDefinition (d, id, b, f, e) + | stre = assumption_token; bl = LIST1 simple_binder_coe -> + VernacAssumption (stre, bl) + | stre = assumptions_token; bl = LIST1 simple_binder_coe -> + test_plurial_form bl; + VernacAssumption (stre, bl) + (* Gallina inductive declarations *) + | OPT[IDENT "Mutual"]; f = finite_token; + indl = LIST1 inductive_definition SEP "with" -> + VernacInductive (f,indl) + | IDENT "Fixpoint"; recs = LIST1 rec_definition SEP "with" -> + VernacFixpoint recs + | IDENT "CoFixpoint"; corecs = LIST1 corec_definition SEP "with" -> + VernacCoFixpoint corecs + | IDENT "Scheme"; l = LIST1 scheme SEP "with" -> VernacScheme l ] ] + ; + gallina_ext: + [ [ record_token; oc = opt_coercion; name = base_ident; + ps = LIST0 simple_binder; ":"; + s = lconstr; ":="; cstr = OPT base_ident; "{"; + fs = LIST0 local_decl_expr; "}" -> + VernacRecord ((oc,name),ps,s,cstr,fs) + | f = finite_token; s = csort; id = base_ident; + indpar = LIST0 simple_binder; ":="; lc = constructor_list -> + VernacInductive (f,[id,indpar,s,lc]) + ] ] + ; + thm_token: + [ [ IDENT "Theorem" -> Theorem + | IDENT "Lemma" -> Lemma + | IDENT "Fact" -> Fact + | IDENT "Remark" -> Remark ] ] + ; + def_token: + [ [ IDENT "Definition" -> (fun _ _ -> ()), Global, GDefinition + | IDENT "Local" -> (fun _ _ -> ()), Local, LDefinition + | IDENT "SubClass" -> Class.add_subclass_hook, Global, GCoercion + | IDENT "Local"; IDENT "SubClass" -> + Class.add_subclass_hook, Local, LCoercion ] ] + ; + assumption_token: + [ [ IDENT "Hypothesis" -> (Local, Logical) + | IDENT "Variable" -> (Local, Definitional) + | IDENT "Axiom" -> (Global, Logical) + | IDENT "Parameter" -> (Global, Definitional) ] ] + ; + assumptions_token: + [ [ IDENT "Hypotheses" -> (Local, Logical) + | IDENT "Variables" -> (Local, Definitional) + | IDENT "Parameters" -> (Global, Definitional) ] ] + ; + finite_token: + [ [ IDENT "Inductive" -> true + | IDENT "CoInductive" -> false ] ] + ; + record_token: + [ [ IDENT "Record" -> () | IDENT "Structure" -> () ] ] + ; + (* Simple definitions *) + def_body: + [ [ bl = LIST0 binder; ":="; red = reduce; c = lconstr -> + (match c with + CCast(_,c,t) -> DefineBody (bl, red, c, Some t) + | _ -> DefineBody (bl, red, c, None)) + | bl = LIST0 binder; ":"; t = lconstr; ":="; red = reduce; c = lconstr -> + DefineBody (bl, red, c, Some t) + | bl = LIST0 binder; ":"; t = lconstr -> + ProveBody (bl, t) ] ] + ; + reduce: + [ [ IDENT "Eval"; r = Tactic.red_expr; "in" -> Some r + | -> None ] ] + ; + (* Inductives and records *) + inductive_definition: + [ [ id = base_ident; indpar = LIST0 simple_binder; ":"; c = lconstr; ":="; + lc = constructor_list -> (id,indpar,c,lc) ] ] + ; + constructor_list: + [ [ "|"; l = LIST1 constructor_binder SEP "|" -> l + | l = LIST1 constructor_binder SEP "|" -> l + | -> [] ] ] + ; + csort: + [ [ s = sort -> CSort (loc,s) ] ] + ; + opt_coercion: + [ [ ">" -> true + | -> false ] ] + ; + (* (co)-fixpoints *) + rec_definition: + [ [ id = base_ident; bl = LIST1 binder_nodef; ":"; type_ = lconstr; + ":="; def = lconstr -> + let ni = List.length (List.flatten (List.map fst bl)) - 1 in + let loc0 = fst (List.hd (fst (List.hd bl))) in + let loc1 = join_loc loc0 (constr_loc type_) in + let loc2 = join_loc loc0 (constr_loc def) in + (id, ni, CProdN (loc1,bl,type_), CLambdaN (loc2,bl,def)) ] ] + ; + corec_definition: + [ [ id = base_ident; ":"; c = lconstr; ":="; def = lconstr -> + (id,c,def) ] ] + ; + (* Inductive schemes *) + scheme: + [ [ id = base_ident; ":="; dep = dep_scheme; "for"; ind = global; + IDENT "Sort"; s = sort -> + (id,dep,ind,s) ] ] + ; + dep_scheme: + [ [ IDENT "Induction" -> true + | IDENT "Minimality" -> false ] ] + ; + (* Various Binders *) + (* ... without coercions *) + simple_binder: + [ [ b = simple_binder_coe -> no_coercion loc b ] ] + ; + binder: + [ [ na = name -> LocalRawAssum([na],CHole loc) + | "("; na = name; ")" -> LocalRawAssum([na],CHole loc) + | "("; na = name; ":"; c = lconstr; ")" + -> LocalRawAssum([na],c) + | "("; na = name; ":="; c = lconstr; ")" -> + LocalRawDef (na,c) + ] ] + ; + binder_nodef: + [ [ b = binder -> + (match b with + LocalRawAssum(l,ty) -> (l,ty) + | LocalRawDef _ -> + Util.user_err_loc + (loc,"fix_param",Pp.str"defined binder not allowed here")) ] ] + ; + (* ... with coercions *) + local_decl_expr: + [ [ id = base_ident -> (false,AssumExpr(id,CHole loc)) + | "("; id = base_ident; ")" -> (false,AssumExpr(id,CHole loc)) + | "("; id = base_ident; oc = of_type_with_opt_coercion; + t = lconstr; ")" -> + (oc,AssumExpr (id,t)) + | "("; id = base_ident; oc = of_type_with_opt_coercion; + t = lconstr; ":="; b = lconstr; ")" -> + (oc,DefExpr (id,b,Some t)) + | "("; id = base_ident; ":="; b = lconstr; ")" -> + match b with + CCast(_,b,t) -> (false,DefExpr(id,b,Some t)) + | _ -> (false,DefExpr(id,b,None)) ] ] + ; + simple_binder_coe: + [ [ id=base_ident -> (false,(id,CHole loc)) + | "("; id = base_ident; ")" -> (false,(id,CHole loc)) + | "("; id = base_ident; oc = of_type_with_opt_coercion; + t = lconstr; ")" -> + (oc,(id,t)) ] ] + ; + constructor_binder: + [ [ id = base_ident; coe = of_type_with_opt_coercion; c = lconstr -> + (coe,(id,c)) ] ] + ; + of_type_with_opt_coercion: + [ [ ":>" -> true + | ":"; ">" -> true + | ":" -> false ] ] + ; +END + + +(* Modules and Sections *) +GEXTEND Gram + GLOBAL: gallina_ext module_expr module_type; + + gallina_ext: + [ [ (* Interactive module declaration *) + IDENT "Module"; id = base_ident; + bl = LIST0 module_binder; mty_o = OPT of_module_type; + mexpr_o = OPT is_module_expr -> + VernacDefineModule (id, bl, mty_o, mexpr_o) + + | IDENT "Module"; "Type"; id = base_ident; + bl = LIST0 module_binder; mty_o = OPT is_module_type -> + VernacDeclareModuleType (id, bl, mty_o) + + | IDENT "Declare"; IDENT "Module"; id = base_ident; + bl = LIST0 module_binder; mty_o = OPT of_module_type; + mexpr_o = OPT is_module_expr -> + VernacDeclareModule (id, bl, mty_o, mexpr_o) + (* Section beginning *) + | IDENT "Section"; id = base_ident -> VernacBeginSection id + | IDENT "Chapter"; id = base_ident -> VernacBeginSection id + + (* This end a Section a Module or a Module Type *) + | IDENT "End"; id = base_ident -> VernacEndSegment id + + (* Requiring an already compiled module *) + | IDENT "Require"; export = export_token; specif = specif_token; + qidl = LIST1 global -> + VernacRequire (export, specif, qidl) + | IDENT "Require"; export = export_token; specif = specif_token; + filename = STRING -> + VernacRequireFrom (export, specif, filename) + | IDENT "Import"; qidl = LIST1 global -> VernacImport (false,qidl) + | IDENT "Export"; qidl = LIST1 global -> VernacImport (true,qidl) ] ] + ; + export_token: + [ [ IDENT "Import" -> Some false + | IDENT "Export" -> Some true + | IDENT "Closed" -> None + | -> Some false ] ] + ; + specif_token: + [ [ IDENT "Implementation" -> Some false + | IDENT "Specification" -> Some true + | -> None ] ] + ; + of_module_type: + [ [ ":"; mty = module_type -> (mty, true) + | "<:"; mty = module_type -> (mty, false) ] ] + ; + is_module_type: + [ [ ":="; mty = module_type -> mty ] ] + ; + is_module_expr: + [ [ ":="; mexpr = module_expr -> mexpr ] ] + ; + + (* Module binder *) + module_binder: + [ [ "("; id = base_ident; ":"; mty = module_type; ")" -> + ([id],mty) ] ] + ; + + (* Module expressions *) + module_expr: + [ [ qid = qualid -> CMEident qid + | me1 = module_expr; me2 = module_expr -> CMEapply (me1,me2) + | "("; me = module_expr; ")" -> me +(* ... *) + ] ] + ; + with_declaration: + [ [ IDENT "Definition"; id = base_ident; ":="; c = Constr.constr -> + CWith_Definition (id,c) + | IDENT "Module"; id = base_ident; ":="; qid = qualid -> + CWith_Module (id,qid) + ] ] + ; + module_type: + [ [ qid = qualid -> CMTEident qid +(* ... *) + | mty = module_type; "with"; decl = with_declaration -> + CMTEwith (mty,decl) ] ] + ; +END + +(* Extensions: implicits, coercions, etc. *) +GEXTEND Gram + GLOBAL: gallina_ext; + + gallina_ext: + [ [ (* Transparent and Opaque *) + IDENT "Transparent"; l = LIST1 global -> VernacSetOpacity (false, l) + | IDENT "Opaque"; l = LIST1 global -> VernacSetOpacity (true, l) + + (* Canonical structure *) + | IDENT "Canonical"; IDENT "Structure"; qid = global -> + VernacCanonical qid + | IDENT "Canonical"; IDENT "Structure"; qid = global; d = def_body -> + let s = Ast.coerce_global_to_id qid in + VernacDefinition (Global,s,d,Recordobj.add_object_hook,SCanonical) + + (* Coercions *) + | IDENT "Coercion"; qid = global; d = def_body -> + let s = Ast.coerce_global_to_id qid in + VernacDefinition (Global,s,d,Class.add_coercion_hook,GCoercion) + | IDENT "Coercion"; IDENT "Local"; qid = global; d = def_body -> + let s = Ast.coerce_global_to_id qid in + VernacDefinition (Local,s,d,Class.add_coercion_hook,LCoercion) + | IDENT "Identity"; IDENT "Coercion"; IDENT "Local"; f = base_ident; + ":"; s = class_rawexpr; ">->"; t = class_rawexpr -> + VernacIdentityCoercion (Local, f, s, t) + | IDENT "Identity"; IDENT "Coercion"; f = base_ident; ":"; + s = class_rawexpr; ">->"; t = class_rawexpr -> + VernacIdentityCoercion (Global, f, s, t) + | IDENT "Coercion"; IDENT "Local"; qid = global; ":"; + s = class_rawexpr; ">->"; t = class_rawexpr -> + VernacCoercion (Local, qid, s, t) + | IDENT "Coercion"; qid = global; ":"; s = class_rawexpr; ">->"; + t = class_rawexpr -> + VernacCoercion (Global, qid, s, t) + + (* Implicit *) + | IDENT "Syntactic"; IDENT "Definition"; id = IDENT; ":="; c = lconstr; + n = OPT [ "|"; n = natural -> n ] -> + let c = match n with + | Some n -> + let l = list_tabulate (fun _ -> (CHole (loc),None)) n in + CApp (loc,c,l) + | None -> c in + VernacNotation ("'"^id^"'",c,[],None,None) + | IDENT "Implicits"; qid = global; "["; l = LIST0 natural; "]" -> + VernacDeclareImplicits (qid,Some l) + | IDENT "Implicits"; qid = global -> VernacDeclareImplicits (qid,None) + + (* For compatibility *) + | IDENT "Implicit"; IDENT "Arguments"; IDENT "On" -> + VernacSetOption + (Goptions.SecondaryTable ("Implicit","Arguments"), + BoolValue true) + | IDENT "Implicit"; IDENT "Arguments"; IDENT "Off" -> + VernacSetOption + (Goptions.SecondaryTable ("Implicit","Arguments"), + BoolValue false) ] ] + ; +END + +GEXTEND Gram + GLOBAL: command check_command class_rawexpr; + + command: + [ [ IDENT "Comments"; l = LIST0 comment -> VernacComments l + + (* System directory *) + | IDENT "Pwd" -> VernacChdir None + | IDENT "Cd" -> VernacChdir None + | IDENT "Cd"; dir = STRING -> VernacChdir (Some dir) + + (* Toplevel control *) + | IDENT "Drop" -> VernacToplevelControl Drop + | IDENT "ProtectedLoop" -> VernacToplevelControl ProtectedLoop + | IDENT "Quit" -> VernacToplevelControl Quit + + | IDENT "Load"; verbosely = [ IDENT "Verbose" -> true | -> false ]; + s = [ s = STRING -> s | s = IDENT -> s ] -> + VernacLoad (verbosely, s) + | IDENT "Declare"; IDENT "ML"; IDENT "Module"; l = LIST1 STRING -> + VernacDeclareMLModule l + + (* Dump of the universe graph - to file or to stdout *) + | IDENT "Dump"; IDENT "Universes"; fopt = OPT STRING -> + VernacPrint (PrintUniverses fopt) + + | IDENT "Locate"; l = locatable -> VernacLocate l + + (* Managing load paths *) + | IDENT "Add"; IDENT "LoadPath"; dir = STRING; alias = as_dirpath -> + VernacAddLoadPath (false, dir, alias) + | IDENT "Add"; IDENT "Rec"; IDENT "LoadPath"; dir = STRING; + alias = as_dirpath -> VernacAddLoadPath (true, dir, alias) + | IDENT "Remove"; IDENT "LoadPath"; dir = STRING -> + VernacRemoveLoadPath dir + + (* For compatibility *) + | IDENT "AddPath"; dir = STRING; "as"; alias = as_dirpath -> + VernacAddLoadPath (false, dir, alias) + | IDENT "AddRecPath"; dir = STRING; "as"; alias = as_dirpath -> + VernacAddLoadPath (true, dir, alias) + | IDENT "DelPath"; dir = STRING -> + VernacRemoveLoadPath dir + + (* Type-Checking (pas dans le refman) *) + | "Type"; c = lconstr -> VernacGlobalCheck c + + (* Printing (careful factorization of entries) *) + | IDENT "Print"; p = printable -> VernacPrint p + | IDENT "Print"; qid = global -> VernacPrint (PrintName qid) + | IDENT "Print" -> VernacPrint PrintLocalContext + | IDENT "Print"; IDENT "Module"; "Type"; qid = global -> + VernacPrint (PrintModuleType qid) + | IDENT "Print"; IDENT "Module"; qid = global -> + VernacPrint (PrintModule qid) + | IDENT "Inspect"; n = natural -> VernacPrint (PrintInspect n) + + (* Searching the environment *) + | IDENT "Search"; qid = global; l = in_or_out_modules -> + VernacSearch (SearchHead qid, l) + | IDENT "SearchPattern"; c = constr_pattern; l = in_or_out_modules -> + VernacSearch (SearchPattern c, l) + | IDENT "SearchRewrite"; c = constr_pattern; l = in_or_out_modules -> + VernacSearch (SearchRewrite c, l) + | IDENT "SearchAbout"; qid = global; l = in_or_out_modules -> + VernacSearch (SearchAbout qid, l) + + | IDENT "Add"; IDENT "ML"; IDENT "Path"; dir = STRING -> + VernacAddMLPath (false, dir) + | IDENT "Add"; IDENT "Rec"; IDENT "ML"; IDENT "Path"; dir = STRING -> + VernacAddMLPath (true, dir) + + (* Pour intervenir sur les tables de paramètres *) + | "Set"; table = IDENT; field = IDENT; v = option_value -> + VernacSetOption (SecondaryTable (table,field),v) + | "Set"; table = IDENT; field = IDENT; lv = LIST1 option_ref_value -> + VernacAddOption (SecondaryTable (table,field),lv) + | "Set"; table = IDENT; field = IDENT -> + VernacSetOption (SecondaryTable (table,field),BoolValue true) + | IDENT "Unset"; table = IDENT; field = IDENT -> + VernacUnsetOption (SecondaryTable (table,field)) + | IDENT "Unset"; table = IDENT; field = IDENT; lv = LIST1 option_ref_value -> + VernacRemoveOption (SecondaryTable (table,field),lv) + | "Set"; table = IDENT; value = option_value -> + VernacSetOption (PrimaryTable table, value) + | "Set"; table = IDENT -> + VernacSetOption (PrimaryTable table, BoolValue true) + | IDENT "Unset"; table = IDENT -> + VernacUnsetOption (PrimaryTable table) + + | IDENT "Print"; IDENT "Table"; table = IDENT; field = IDENT -> + VernacPrintOption (SecondaryTable (table,field)) + | IDENT "Print"; IDENT "Table"; table = IDENT -> + VernacPrintOption (PrimaryTable table) + + | IDENT "Add"; table = IDENT; field = IDENT; v = LIST1 option_ref_value + -> VernacAddOption (SecondaryTable (table,field), v) + + (* Un value global ci-dessous va être caché par un field au dessus! *) + | IDENT "Add"; table = IDENT; v = LIST1 option_ref_value -> + VernacAddOption (PrimaryTable table, v) + + | IDENT "Test"; table = IDENT; field = IDENT; v = LIST1 option_ref_value + -> VernacMemOption (SecondaryTable (table,field), v) + | IDENT "Test"; table = IDENT; field = IDENT -> + VernacPrintOption (SecondaryTable (table,field)) + | IDENT "Test"; table = IDENT; v = LIST1 option_ref_value -> + VernacMemOption (PrimaryTable table, v) + | IDENT "Test"; table = IDENT -> + VernacPrintOption (PrimaryTable table) + + | IDENT "Remove"; table = IDENT; field = IDENT; v= LIST1 option_ref_value + -> VernacRemoveOption (SecondaryTable (table,field), v) + | IDENT "Remove"; table = IDENT; v = LIST1 option_ref_value -> + VernacRemoveOption (PrimaryTable table, v) ] ] + ; + check_command: (* TODO: rapprocher Eval et Check *) + [ [ IDENT "Eval"; r = Tactic.red_expr; "in"; c = lconstr -> + fun g -> VernacCheckMayEval (Some r, g, c) + | IDENT "Check"; c = lconstr -> + fun g -> VernacCheckMayEval (None, g, c) ] ] + ; + printable: + [ [ IDENT "Term"; qid = global -> PrintName qid + | IDENT "All" -> PrintFullContext + | IDENT "Section"; s = global -> PrintSectionContext s + | IDENT "Grammar"; uni = IDENT; ent = IDENT -> + (* This should be in "syntax" section but is here for factorization*) + PrintGrammar (uni, ent) + | IDENT "LoadPath" -> PrintLoadPath + | IDENT "Modules" -> PrintModules + + | IDENT "ML"; IDENT "Path" -> PrintMLLoadPath + | IDENT "ML"; IDENT "Modules" -> PrintMLModules + | IDENT "Graph" -> PrintGraph + | IDENT "Classes" -> PrintClasses + | IDENT "Coercions" -> PrintCoercions + | IDENT "Coercion"; IDENT "Paths"; s = class_rawexpr; t = class_rawexpr + -> PrintCoercionPaths (s,t) + | IDENT "Tables" -> PrintTables + | IDENT "Proof"; qid = global -> PrintOpaqueName qid + | IDENT "Hint" -> PrintHintGoal + | IDENT "Hint"; qid = global -> PrintHint qid + | IDENT "Hint"; "*" -> PrintHintDb + | IDENT "HintDb"; s = IDENT -> PrintHintDbName s + | IDENT "Scope"; s = IDENT -> PrintScope s ] ] + ; + class_rawexpr: + [ [ IDENT "FUNCLASS" -> FunClass + | IDENT "SORTCLASS" -> SortClass + | qid = global -> RefClass qid ] ] + ; + locatable: + [ [ qid = global -> LocateTerm qid + | IDENT "File"; f = STRING -> LocateFile f + | IDENT "Library"; qid = global -> LocateLibrary qid + | s = STRING -> LocateNotation s ] ] + ; + option_value: + [ [ n = integer -> IntValue n + | s = STRING -> StringValue s ] ] + ; + option_ref_value: + [ [ id = global -> QualidRefValue id + | s = STRING -> StringRefValue s ] ] + ; + as_dirpath: + [ [ d = OPT [ "as"; d = dirpath -> d ] -> d ] ] + ; + in_or_out_modules: + [ [ IDENT "inside"; l = LIST1 global -> SearchInside l + | IDENT "outside"; l = LIST1 global -> SearchOutside l + | -> SearchOutside [] ] ] + ; + comment: + [ [ c = constr -> CommentConstr c + | s = STRING -> CommentString s + | n = natural -> CommentInt n ] ] + ; +END; + +GEXTEND Gram + command: + [ [ +(* State management *) + IDENT "Write"; IDENT "State"; s = IDENT -> VernacWriteState s + | IDENT "Write"; IDENT "State"; s = STRING -> VernacWriteState s + | IDENT "Restore"; IDENT "State"; s = IDENT -> VernacRestoreState s + | IDENT "Restore"; IDENT "State"; s = STRING -> VernacRestoreState s + +(* Resetting *) + | IDENT "Reset"; id = identref -> VernacResetName id + | IDENT "Reset"; IDENT "Initial" -> VernacResetInitial + | IDENT "Back" -> VernacBack 1 + | IDENT "Back"; n = natural -> VernacBack n + +(* Tactic Debugger *) + | IDENT "Debug"; IDENT "On" -> VernacDebug true + | IDENT "Debug"; IDENT "Off" -> VernacDebug false + + ] ]; + END +;; + +(* Grammar extensions *) + +GEXTEND Gram + GLOBAL: syntax; + + syntax: + [ [ IDENT "Open"; IDENT "Scope"; sc = IDENT -> VernacOpenScope sc + + | IDENT "Delimits"; IDENT "Scope"; sc = IDENT; "with"; key = IDENT -> + VernacDelimiters (sc,key) + + | IDENT "Arguments"; IDENT "Scope"; qid = global; + "["; scl = LIST0 opt_scope; "]" -> VernacArgumentsScope (qid,scl) + + | IDENT "Infix"; a = entry_prec; n = OPT natural; op = STRING; + p = global; + modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ]; + sc = OPT [ ":"; sc = IDENT -> sc ] -> + let (a,n,b) = Metasyntax.interp_infix_modifiers a n modl in + VernacInfix (a,n,op,p,b,None,sc) + | IDENT "Notation"; s = IDENT; ":="; c = constr -> + VernacNotation ("'"^s^"'",c,[],None,None) + | IDENT "Notation"; s = STRING; ":="; c = constr; + modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ]; + sc = OPT [ ":"; sc = IDENT -> sc ] -> + VernacNotation (s,c,modl,None,sc) + + | IDENT "Grammar"; IDENT "tactic"; IDENT "simple_tactic"; + OPT [ ":"; IDENT "tactic" ]; ":="; + OPT "|"; tl = LIST0 grammar_tactic_rule SEP "|" -> + VernacTacticGrammar tl + + | IDENT "Grammar"; u = univ; + tl = LIST1 grammar_entry SEP "with" -> + VernacGrammar (rename_command_entry u,tl) + + | IDENT "Syntax"; u = univ; el = LIST1 syntax_entry SEP "," -> + VernacSyntax (u,el) + + | IDENT "Uninterpreted"; IDENT "Notation"; s = STRING; + l = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ] + -> VernacSyntaxExtension (s,l) + + (* "Print" "Grammar" should be here but is in "command" entry in order + to factorize with other "Print"-based vernac entries *) + ] ] + ; + univ: + [ [ univ = IDENT -> + set_default_action_parser (parser_type_from_name univ); univ ] ] + ; + syntax_modifier: + [ [ x = IDENT; IDENT "at"; IDENT "level"; n = natural -> + SetItemLevel ([x],n) + | x = IDENT; ","; l = LIST1 IDENT SEP ","; IDENT "at"; IDENT "level"; + n = natural -> SetItemLevel (x::l,n) + | IDENT "at"; IDENT "level"; n = natural -> SetLevel n + | IDENT "left"; IDENT "associativity" -> SetAssoc Gramext.LeftA + | IDENT "right"; IDENT "associativity" -> SetAssoc Gramext.RightA + | IDENT "no"; IDENT "associativity" -> SetAssoc Gramext.NonA + | x = IDENT; typ = syntax_extension_type -> SetEntryType (x,typ) + | IDENT "only"; IDENT "parsing" -> SetOnlyParsing ] ] + ; + syntax_extension_type: + [ [ IDENT "ident" -> ETIdent | IDENT "global" -> ETReference + | IDENT "bigint" -> ETBigint + | e=IDENT -> ETOther("constr",e) + ] ] + ; + opt_scope: + [ [ IDENT "_" -> None | sc = IDENT -> Some sc ] ] + ; + (* Syntax entries for Grammar. Only grammar_entry is exported *) + grammar_entry: + [[ nont = IDENT; set_entry_type; ":="; + ep = entry_prec; OPT "|"; rl = LIST0 grammar_rule SEP "|" -> + (rename_command_entry nont,ep,rl) ]] + ; + entry_prec: + [[ IDENT "LEFTA" -> Some Gramext.LeftA + | IDENT "RIGHTA" -> Some Gramext.RightA + | IDENT "NONA" -> Some Gramext.NonA + | -> None ]] + ; + grammar_tactic_rule: + [[ name = rule_name; "["; s = STRING; pil = LIST0 production_item; "]"; + "->"; "["; t = Tactic.tactic; "]" -> (name, (s,pil), t) ]] + ; + grammar_rule: + [[ name = rule_name; "["; pil = LIST0 production_item; "]"; "->"; + a = action -> (name, pil, a) ]] + ; + rule_name: + [[ name = IDENT -> name ]] + ; + production_item: + [[ s = STRING -> VTerm s + | nt = non_terminal; po = OPT [ "("; p = METAIDENT; ")" -> p ] -> + match po with + | Some p -> VNonTerm (loc,nt,Some (Names.id_of_string p)) + | _ -> VNonTerm (loc,nt,None) ]] + ; + non_terminal: + [[ u = IDENT; ":"; nt = IDENT -> + NtQual(rename_command_entry u, rename_command_entry nt) + | nt = IDENT -> NtShort (rename_command_entry nt) ]] + ; + + + (* Syntax entries for Syntax. Only syntax_entry is exported *) + syntax_entry: + [ [ IDENT "level"; p = precedence; ":"; + OPT "|"; rl = LIST1 syntax_rule SEP "|" -> (p,rl) ] ] + ; + syntax_rule: + [ [ nm = IDENT; "["; s = astpat; "]"; "->"; u = unparsing -> (nm,s,u) ] ] + ; + precedence: + [ [ a = natural -> a +(* | "["; a1 = natural; a2 = natural; a3 = natural; "]" -> (a1,a2,a3)*) + ] ] + ; + unparsing: + [ [ "["; ll = LIST0 next_hunks; "]" -> ll ] ] + ; + next_hunks: + [ [ IDENT "FNL" -> UNP_FNL + | IDENT "TAB" -> UNP_TAB + | c = STRING -> RO c + | "["; + x = + [ b = box; ll = LIST0 next_hunks -> UNP_BOX (b,ll) + | n = natural; m = natural -> UNP_BRK (n, m) + | IDENT "TBRK"; n = natural; m = natural -> UNP_TBRK (n, m) ]; + "]" -> x + | e = Prim.ast; oprec = OPT [ ":"; pr = paren_reln_or_extern -> pr ] -> + match oprec with + | Some (ext,pr) -> PH (e,ext,pr) + | None -> PH (e,None,Any) + ]] + ; + box: + [ [ "<"; bk = box_kind; ">" -> bk ] ] + ; + box_kind: + [ [ IDENT "h"; n = natural -> PpHB n + | IDENT "v"; n = natural -> PpVB n + | IDENT "hv"; n = natural -> PpHVB n + | IDENT "hov"; n = natural -> PpHOVB n + | IDENT "t" -> PpTB ] ] + ; + paren_reln_or_extern: + [ [ IDENT "L" -> None, L + | IDENT "E" -> None, E + | pprim = STRING; precrec = OPT [ ":"; p = precedence -> p ] -> + match precrec with + | Some p -> Some pprim, Prec p + | None -> Some pprim, Any ] ] + ; + (* meta-syntax entries *) + astpat: + [ [ "<<" ; a = Prim.ast; ">>" -> a + | a = Constr.lconstr -> + Termast.ast_of_rawconstr + (Constrintern.interp_rawconstr Evd.empty (Global.env()) a) + ] ] + ; + action: + [ [ IDENT "let"; p = Prim.astlist; et = set_internal_entry_type; + "="; e1 = action; "in"; e = action -> Ast.CaseAction (loc,e1,et,[p,e]) + | IDENT "case"; a = action; et = set_internal_entry_type; "of"; + cl = LIST1 case SEP "|"; IDENT "esac" -> Ast.CaseAction (loc,a,et,cl) + | "["; a = default_action_parser; "]" -> Ast.SimpleAction (loc,a) ] ] + ; + case: + [[ p = Prim.astlist; "->"; a = action -> (p,a) ]] + ; + set_internal_entry_type: + [[ ":"; IDENT "ast"; IDENT "list" -> Ast.ETastl + | [ ":"; IDENT "ast" -> () | -> () ] -> Ast.ETast ]] + ; + set_entry_type: + [[ ":"; et = entry_type -> set_default_action_parser et + | -> () ]] + ; + entry_type: + [[ IDENT "ast"; IDENT "list" -> Util.error "type ast list no longer supported" + | IDENT "ast" -> Util.error "type ast no longer supported" + | IDENT "constr" -> ConstrParser + | IDENT "pattern" -> CasesPatternParser + | IDENT "tactic" -> assert false + | IDENT "vernac" -> Util.error "vernac extensions no longer supported" ] ] + ; +END + +(* Reinstall tactic and vernac extensions *) +let _ = Egrammar.reset_extend_grammars_v8() |