PcoqThe parser of Coq
include Gramlib.Grammar.S
  with type keyword_state := CLexer.keyword_state
   and type te := Tok.t
   and type 'a pattern := 'a Tok.p
   and type 'a with_gstate := 'a
   and type 'a with_kwstate := 'a
   and type 'a with_estate := 'a
   and type 'a mod_estate := 'aType combinators to factor the module type between explicit state passing in Grammar and global state in Pcoq
module Parsable : sig ... endmodule Entry : sig ... endmodule Symbol : sig ... endmodule Rule : sig ... endmodule Rules : sig ... endmodule Production : sig ... endtype 'a single_extend_statement =
  string option * Gramlib.Gramext.g_assoc option * 'a Production.t listtype 'a extend_statement = | | Reuse of string option * 'a Production.t list | (* Extend an existing level by its optional given name. If None, picks the topmost level.*) | 
| | Fresh of Gramlib.Gramext.position * 'a single_extend_statement list | (* Create a level at the given position.*) | 
val generalize_symbol : 
  ( 'a, 'tr, 'c ) Symbol.t ->
  ( 'a, Gramlib.Grammar.norec, 'c ) Symbol.t optionval level_of_nonterm : 
  ( 'a, Gramlib.Grammar.norec, 'c ) Symbol.t ->
  string optionmodule Lookahead : sig ... endval terminal : string -> string Tok.pWhen string is not an ident, returns a keyword.
The parser of Coq is built from three kinds of rule declarations:
Note that parsing a Coq document is in essence stateful: the parser needs to recognize commands that start proofs and use a different parsing entry point for them.
We thus provide two different interfaces: the "raw" parsing interface, in the style of camlp5, which provides more flexibility, and a more specialize "parse_vernac" one, which will indeed adjust the state as needed.
Dynamic extension of rules
For constr notations, dynamic addition of new rules is done in several steps:
String "x"; String "+"; String "y" : symbol_token list | | interpreted as a mixed parsing/printing production | by Metasyntax.analyse_notation_tokens V NonTerminal "x"; Terminal "+"; NonTerminal "y" : symbol list | | translated to a parsing production by Metasyntax.make_production V GramConstrNonTerminal (ETConstr (NextLevel,(BorderProd Left,LeftA)),
                              Some "x");
       GramConstrTerminal ("","+");
       GramConstrNonTerminal (ETConstr (NextLevel,(BorderProd Right,LeftA)),
                              Some "y") : grammar_constr_prod_item list | | Egrammar.make_constr_prod_item V Gramext.g_symbol list which is sent to camlp5For user level tactic notations, dynamic addition of new rules is also done in several steps:
TacTerm "f"; TacNonTerm ("constr", Some "x") : grammar_tactic_prod_item_expr list | | Metasyntax.interp_prod_item V GramTerminal "f";
       GramNonTerminal (ConstrArgType, Aentry ("constr","constr"), Some "x") : grammar_prod_item list | | Egrammar.make_prod_item V Gramext.g_symbol listFor TACTIC/VERNAC/ARGUMENT EXTEND, addition of new rules is done as follows:
GramTerminal "f";
       GramNonTerminal (ConstrArgType, Aentry ("constr","constr"), Some "x") | | Egrammar.make_prod_item V Gramext.g_symbol listParse a string
val create_generic_entry2 : 
  string ->
  ( 'a, Genarg.rlevel ) Genarg.abstract_argument_type ->
  'a Entry.tval register_grammar : 
  ( 'raw, 'glb, 'top ) Genarg.genarg_type ->
  'raw Entry.t ->
  unitval genarg_grammar : ( 'raw, 'glb, 'top ) Genarg.genarg_type -> 'raw Entry.tmodule Prim : sig ... endmodule Constr : sig ... endmodule Module : sig ... endval epsilon_value : 
  ( 'a -> 'self ) ->
  ( 'self, _, 'a ) Symbol.t ->
  'self optionval grammar_extend : 'a Entry.t -> 'a extend_statement -> unitExtend the grammar of Coq, without synchronizing it with the backtracking mechanism. This means that grammar extensions defined this way will survive an undo.
type gram_reinit = Gramlib.Gramext.g_assoc * Gramlib.Gramext.positionType of reinitialization data
type extend_rule = | | ExtendRule : 'a Entry.t * 'a extend_statement -> extend_rule | 
| | ExtendRuleReinit : 'a Entry.t
  * gram_reinit
  * 'a extend_statement -> extend_rule | 
type 'a grammar_extension = {| gext_fun : 'a -> GramState.t -> extend_rule list * GramState.t; | 
| gext_eq : 'a -> 'a -> bool; | 
}Grammar extension entry point. Given some 'a and a current grammar state, such a function must produce the list of grammar extensions that will be applied in the same order and kept synchronized w.r.t. the summary, together with a new state. It should be pure.
val create_grammar_command : 
  string ->
  'a grammar_extension ->
  'a grammar_commandCreate a new grammar-modifying command with the given name. The extension function is called to generate the rules for a given data.
val extend_grammar_command : 'a grammar_command -> 'a -> unitExtend the grammar of Coq with the given data.
type ('a, 'b) entry_extension = {| eext_fun : 'a -> GramState.t -> string list * GramState.t; | 
| eext_eq : 'a -> 'a -> bool; | 
}Entry extension entry point. Given some 'a and a current grammar state, such a function must produce the list of entry extensions that will be created and kept synchronized w.r.t. the summary, together with a new state. It should be pure.
val create_entry_command : 
  string ->
  ( 'a, 'b ) entry_extension ->
  ( 'a, 'b ) entry_commandCreate a new entry-creating command with the given name. The extension function is called to generate the new entries for a given data.
val extend_entry_command : ( 'a, 'b ) entry_command -> 'a -> 'b Entry.t listCreate new synchronized entries using the provided data.
val find_custom_entry : ( 'a, 'b ) entry_command -> string -> 'b Entry.tFind an entry generated by the synchronized system in the current state.
val parser_summary_tag : frozen_t Summary.Dyn.tagRegistering grammars by name
val register_grammars_by_name : string -> Entry.any_t list -> unitval find_grammars_by_name : string -> Entry.any_t listval freeze : unit -> frozen_tParsing state handling
val unfreeze : frozen_t -> unitval get_keyword_state : unit -> CLexer.keyword_stateval set_keyword_state : CLexer.keyword_state -> unit