diff options
author | Enrico Tassi <gareuselesinge@debian.org> | 2015-01-25 14:42:51 +0100 |
---|---|---|
committer | Enrico Tassi <gareuselesinge@debian.org> | 2015-01-25 14:42:51 +0100 |
commit | 7cfc4e5146be5666419451bdd516f1f3f264d24a (patch) | |
tree | e4197645da03dc3c7cc84e434cc31d0a0cca7056 /parsing/egrammar.ml | |
parent | 420f78b2caeaaddc6fe484565b2d0e49c66888e5 (diff) |
Imported Upstream version 8.5~beta1+dfsg
Diffstat (limited to 'parsing/egrammar.ml')
-rw-r--r-- | parsing/egrammar.ml | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/parsing/egrammar.ml b/parsing/egrammar.ml deleted file mode 100644 index 6deb7622..00000000 --- a/parsing/egrammar.ml +++ /dev/null @@ -1,368 +0,0 @@ -(************************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2014 *) -(* \VV/ **************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(************************************************************************) - -open Pp -open Compat -open Util -open Pcoq -open Extend -open Ppextend -open Topconstr -open Genarg -open Libnames -open Nameops -open Tacexpr -open Names -open Vernacexpr - -(**************************************************************************) -(* - * --- Note on the mapping of grammar productions to camlp4 actions --- - * - * Translation of environments: a production - * [ nt1(x1) ... nti(xi) ] -> act(x1..xi) - * is written (with camlp4 conventions): - * (fun vi -> .... (fun v1 -> act(v1 .. vi) )..) - * where v1..vi are the values generated by non-terminals nt1..nti. - * Since the actions are executed by substituting an environment, - * the make_*_action family build the following closure: - * - * ((fun env -> - * (fun vi -> - * (fun env -> ... - * - * (fun v1 -> - * (fun env -> gram_action .. env act) - * ((x1,v1)::env)) - * ...) - * ((xi,vi)::env))) - * []) - *) - -(**********************************************************************) -(** Declare Notations grammar rules *) - -let constr_expr_of_name (loc,na) = match na with - | Anonymous -> CHole (loc,None) - | Name id -> CRef (Ident (loc,id)) - -let cases_pattern_expr_of_name (loc,na) = match na with - | Anonymous -> CPatAtom (loc,None) - | Name id -> CPatAtom (loc,Some (Ident (loc,id))) - -type grammar_constr_prod_item = - | GramConstrTerminal of Tok.t - | GramConstrNonTerminal of constr_prod_entry_key * identifier option - | GramConstrListMark of int * bool - (* tells action rule to make a list of the n previous parsed items; - concat with last parsed list if true *) - -let make_constr_action - (f : loc -> constr_notation_substitution -> constr_expr) pil = - let rec make (constrs,constrlists,binders as fullsubst) = function - | [] -> - Gram.action (fun loc -> f loc fullsubst) - | (GramConstrTerminal _ | GramConstrNonTerminal (_,None)) :: tl -> - (* parse a non-binding item *) - Gram.action (fun _ -> make fullsubst tl) - | GramConstrNonTerminal (typ, Some _) :: tl -> - (* parse a binding non-terminal *) - (match typ with - | (ETConstr _| ETOther _) -> - Gram.action (fun (v:constr_expr) -> - make (v :: constrs, constrlists, binders) tl) - | ETReference -> - Gram.action (fun (v:reference) -> - make (CRef v :: constrs, constrlists, binders) tl) - | ETName -> - Gram.action (fun (na:name located) -> - make (constr_expr_of_name na :: constrs, constrlists, binders) tl) - | ETBigint -> - Gram.action (fun (v:Bigint.bigint) -> - make (CPrim(dummy_loc,Numeral v) :: constrs, constrlists, binders) tl) - | ETConstrList (_,n) -> - Gram.action (fun (v:constr_expr list) -> - make (constrs, v::constrlists, binders) tl) - | ETBinder _ | ETBinderList (true,_) -> - Gram.action (fun (v:local_binder list) -> - make (constrs, constrlists, v::binders) tl) - | ETBinderList (false,_) -> - Gram.action (fun (v:local_binder list list) -> - make (constrs, constrlists, List.flatten v::binders) tl) - | ETPattern -> - failwith "Unexpected entry of type cases pattern") - | GramConstrListMark (n,b) :: tl -> - (* Rebuild expansions of ConstrList *) - let heads,constrs = list_chop n constrs in - let constrlists = - if b then (heads@List.hd constrlists)::List.tl constrlists - else heads::constrlists - in make (constrs, constrlists, binders) tl - in - make ([],[],[]) (List.rev pil) - -let check_cases_pattern_env loc (env,envlist,hasbinders) = - if hasbinders then error_invalid_pattern_notation loc else (env,envlist) - -let make_cases_pattern_action - (f : loc -> cases_pattern_notation_substitution -> cases_pattern_expr) pil = - let rec make (env,envlist,hasbinders as fullenv) = function - | [] -> - Gram.action (fun loc -> f loc (check_cases_pattern_env loc fullenv)) - | (GramConstrTerminal _ | GramConstrNonTerminal (_,None)) :: tl -> - (* parse a non-binding item *) - Gram.action (fun _ -> make fullenv tl) - | GramConstrNonTerminal (typ, Some _) :: tl -> - (* parse a binding non-terminal *) - (match typ with - | ETConstr _ -> (* pattern non-terminal *) - Gram.action (fun (v:cases_pattern_expr) -> - make (v::env, envlist, hasbinders) tl) - | ETReference -> - Gram.action (fun (v:reference) -> - make (CPatAtom (dummy_loc,Some v) :: env, envlist, hasbinders) tl) - | ETName -> - Gram.action (fun (na:name located) -> - make (cases_pattern_expr_of_name na :: env, envlist, hasbinders) tl) - | ETBigint -> - Gram.action (fun (v:Bigint.bigint) -> - make (CPatPrim (dummy_loc,Numeral v) :: env, envlist, hasbinders) tl) - | ETConstrList (_,_) -> - Gram.action (fun (vl:cases_pattern_expr list) -> - make (env, vl :: envlist, hasbinders) tl) - | ETBinder _ | ETBinderList (true,_) -> - Gram.action (fun (v:local_binder list) -> - make (env, envlist, hasbinders) tl) - | ETBinderList (false,_) -> - Gram.action (fun (v:local_binder list list) -> - make (env, envlist, true) tl) - | (ETPattern | ETOther _) -> - anomaly "Unexpected entry of type cases pattern or other") - | GramConstrListMark (n,b) :: tl -> - (* Rebuild expansions of ConstrList *) - let heads,env = list_chop n env in - if b then - make (env,(heads@List.hd envlist)::List.tl envlist,hasbinders) tl - else - make (env,heads::envlist,hasbinders) tl - in - make ([],[],false) (List.rev pil) - -let rec make_constr_prod_item assoc from forpat = function - | GramConstrTerminal tok :: l -> - gram_token_of_token tok :: make_constr_prod_item assoc from forpat l - | GramConstrNonTerminal (nt, ovar) :: l -> - symbol_of_constr_prod_entry_key assoc from forpat nt - :: make_constr_prod_item assoc from forpat l - | GramConstrListMark _ :: l -> - make_constr_prod_item assoc from forpat l - | [] -> - [] - -let prepare_empty_levels forpat (pos,p4assoc,name,reinit) = - let entry = - if forpat then weaken_entry Constr.pattern - else weaken_entry Constr.operconstr in - grammar_extend entry reinit (pos,[(name, p4assoc, [])]) - -let pure_sublevels level symbs = - map_succeed - (function s -> - let i = level_of_snterml s in - if level = Some i then failwith ""; - i) - symbs - -let extend_constr (entry,level) (n,assoc) mkact forpat rules = - List.fold_left (fun nb pt -> - let symbs = make_constr_prod_item assoc n forpat pt in - let pure_sublevels = pure_sublevels level symbs in - let needed_levels = register_empty_levels forpat pure_sublevels in - let pos,p4assoc,name,reinit = find_position forpat assoc level in - let nb_decls = List.length needed_levels + 1 in - List.iter (prepare_empty_levels forpat) needed_levels; - grammar_extend entry reinit (pos,[(name, p4assoc, [symbs, mkact pt])]); - nb_decls) 0 rules - -let extend_constr_notation (n,assoc,ntn,rules) = - (* Add the notation in constr *) - let mkact loc env = CNotation (loc,ntn,env) in - let e = interp_constr_entry_key false (ETConstr (n,())) in - let nb = extend_constr e (ETConstr(n,()),assoc) (make_constr_action mkact) false rules in - (* Add the notation in cases_pattern *) - let mkact loc env = CPatNotation (loc,ntn,env) in - let e = interp_constr_entry_key true (ETConstr (n,())) in - let nb' = extend_constr e (ETConstr (n,()),assoc) (make_cases_pattern_action mkact) - true rules in - nb+nb' - -(**********************************************************************) -(** Making generic actions in type generic_argument *) - -let make_generic_action - (f:loc -> ('b * raw_generic_argument) list -> 'a) pil = - let rec make env = function - | [] -> - Gram.action (fun loc -> f loc env) - | None :: tl -> (* parse a non-binding item *) - Gram.action (fun _ -> make env tl) - | Some (p, t) :: tl -> (* non-terminal *) - Gram.action (fun v -> make ((p,in_generic t v) :: env) tl) in - make [] (List.rev pil) - -let make_rule univ f g pt = - let (symbs,ntl) = List.split (List.map g pt) in - let act = make_generic_action f ntl in - (symbs, act) - -(**********************************************************************) -(** Grammar extensions declared at ML level *) - -type grammar_prod_item = - | GramTerminal of string - | GramNonTerminal of - loc * argument_type * prod_entry_key * identifier option - -let make_prod_item = function - | GramTerminal s -> (gram_token_of_string s, None) - | GramNonTerminal (_,t,e,po) -> - (symbol_of_prod_entry_key e, Option.map (fun p -> (p,t)) po) - -(* Tactic grammar extensions *) - -let extend_tactic_grammar s gl = - let univ = get_univ "tactic" in - let mkact loc l = Tacexpr.TacExtend (loc,s,List.map snd l) in - let rules = List.map (make_rule univ mkact make_prod_item) gl in - maybe_uncurry (Gram.extend Tactic.simple_tactic) - (None,[(None, None, List.rev rules)]) - -(* Vernac grammar extensions *) - -let vernac_exts = ref [] -let get_extend_vernac_grammars () = !vernac_exts - -let extend_vernac_command_grammar s nt gl = - let nt = Option.default Vernac_.command nt in - vernac_exts := (s,gl) :: !vernac_exts; - let univ = get_univ "vernac" in - let mkact loc l = VernacExtend (s,List.map snd l) in - let rules = List.map (make_rule univ mkact make_prod_item) gl in - maybe_uncurry (Gram.extend nt) (None,[(None, None, List.rev rules)]) - -(**********************************************************************) -(** Grammar declaration for Tactic Notation (Coq level) *) - -let get_tactic_entry n = - if n = 0 then - weaken_entry Tactic.simple_tactic, None - else if n = 5 then - weaken_entry Tactic.binder_tactic, None - else if 1<=n && n<5 then - weaken_entry Tactic.tactic_expr, Some (Compat.Level (string_of_int n)) - else - error ("Invalid Tactic Notation level: "^(string_of_int n)^".") - -(* Declaration of the tactic grammar rule *) - -let head_is_ident = function GramTerminal _::_ -> true | _ -> false - -let add_tactic_entry (key,lev,prods,tac) = - let univ = get_univ "tactic" in - let entry, pos = get_tactic_entry lev in - let rules = - if lev = 0 then begin - if not (head_is_ident prods) then - error "Notation for simple tactic must start with an identifier."; - let mkact s tac loc l = - (TacAlias(loc,s,l,tac):raw_atomic_tactic_expr) in - make_rule univ (mkact key tac) make_prod_item prods - end - else - let mkact s tac loc l = - (TacAtom(loc,TacAlias(loc,s,l,tac)):raw_tactic_expr) in - make_rule univ (mkact key tac) make_prod_item prods in - synchronize_level_positions (); - grammar_extend entry None (pos,[(None, None, List.rev [rules])]); - 1 - -(**********************************************************************) -(** State of the grammar extensions *) - -type notation_grammar = - int * gram_assoc option * notation * grammar_constr_prod_item list list - -type all_grammar_command = - | Notation of - (precedence * tolerability list) * - notation_var_internalization_type list * - notation_grammar - | TacticGrammar of - (string * int * grammar_prod_item list * - (dir_path * Tacexpr.glob_tactic_expr)) - -let (grammar_state : (int * all_grammar_command) list ref) = ref [] - -let extend_grammar gram = - let nb = match gram with - | Notation (_,_,a) -> extend_constr_notation a - | TacticGrammar g -> add_tactic_entry g in - grammar_state := (nb,gram) :: !grammar_state - -let recover_notation_grammar ntn prec = - let l = map_succeed (function - | _, Notation (prec',vars,(_,_,ntn',_ as x)) when prec = prec' & ntn = ntn' -> - vars, x - | _ -> - failwith "") !grammar_state in - assert (List.length l = 1); - List.hd l - -(* Summary functions: the state of the lexer is included in that of the parser. - Because the grammar affects the set of keywords when adding or removing - grammar rules. *) -type frozen_t = all_grammar_command list * Lexer.frozen_t - -let freeze () = (!grammar_state, Lexer.freeze ()) - -(* We compare the current state of the grammar and the state to unfreeze, - by computing the longest common suffixes *) -let factorize_grams l1 l2 = - if l1 == l2 then ([], [], l1) else list_share_tails l1 l2 - -let number_of_entries gcl = - List.fold_left (fun n (p,_) -> n + p) 0 gcl - -let unfreeze (grams, lex) = - let (undo, redo, common) = factorize_grams !grammar_state grams in - let n = number_of_entries undo in - remove_grammars n; - remove_levels n; - grammar_state := common; - Lexer.unfreeze lex; - List.iter extend_grammar (List.rev (List.map snd redo)) - -let init_grammar () = - remove_grammars (number_of_entries !grammar_state); - grammar_state := [] - -let init () = - init_grammar () - -open Summary - -let _ = - declare_summary "GRAMMAR_LEXER" - { freeze_function = freeze; - unfreeze_function = unfreeze; - init_function = init } - -let with_grammar_rule_protection f x = - let fs = freeze () in - try let a = f x in unfreeze fs; a - with reraise -> unfreeze fs; raise reraise |