~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to parsing/egrammar.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
 
 
9
(* $Id: egrammar.ml 11512 2008-10-27 12:28:36Z herbelin $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
open Pcoq
 
14
open Extend
 
15
open Topconstr
 
16
open Genarg
 
17
open Libnames
 
18
open Nameops
 
19
open Tacexpr
 
20
open Names
 
21
open Vernacexpr
 
22
 
 
23
(**************************************************************************)
 
24
(*  
 
25
 * --- Note on the mapping of grammar productions to camlp4 actions ---
 
26
 *  
 
27
 * Translation of environments: a production
 
28
 *   [ nt1(x1) ... nti(xi) ] -> act(x1..xi)
 
29
 * is written (with camlp4 conventions):
 
30
 *   (fun vi -> .... (fun v1 -> act(v1 .. vi) )..)
 
31
 * where v1..vi are the values generated by non-terminals nt1..nti.
 
32
 * Since the actions are executed by substituting an environment,
 
33
 * the make_*_action family build the following closure:
 
34
 *
 
35
 *      ((fun env ->
 
36
 *          (fun vi -> 
 
37
 *             (fun env -> ...
 
38
 *           
 
39
 *                  (fun v1 ->
 
40
 *                     (fun env -> gram_action .. env act)
 
41
 *                     ((x1,v1)::env))
 
42
 *                  ...)
 
43
 *             ((xi,vi)::env)))
 
44
 *         [])
 
45
 *)
 
46
 
 
47
(**********************************************************************)
 
48
(** Declare Notations grammar rules                                   *)
 
49
 
 
50
type prod_item =
 
51
  | Term of Token.pattern
 
52
  | NonTerm of constr_production_entry * 
 
53
      (Names.identifier * constr_production_entry) option
 
54
 
 
55
type 'a action_env = 'a list * 'a list list
 
56
 
 
57
let make_constr_action
 
58
  (f : loc -> constr_expr action_env -> constr_expr) pil =
 
59
  let rec make (env,envlist as fullenv : constr_expr action_env) = function
 
60
    | [] ->
 
61
        Gramext.action (fun loc -> f loc fullenv)
 
62
    | None :: tl -> (* parse a non-binding item *)
 
63
        Gramext.action (fun _ -> make fullenv tl)
 
64
    | Some (p, (ETConstr _| ETOther _)) :: tl -> (* constr non-terminal *)
 
65
        Gramext.action (fun (v:constr_expr) -> make (v :: env, envlist) tl)
 
66
    | Some (p, ETReference) :: tl -> (* non-terminal *)
 
67
        Gramext.action (fun (v:reference) -> make (CRef v :: env, envlist) tl)
 
68
    | Some (p, ETIdent) :: tl -> (* non-terminal *)
 
69
        Gramext.action (fun (v:identifier) ->
 
70
          make (CRef (Ident (dummy_loc,v)) :: env, envlist) tl)
 
71
    | Some (p, ETBigint) :: tl -> (* non-terminal *)
 
72
        Gramext.action (fun (v:Bigint.bigint) ->
 
73
          make (CPrim (dummy_loc,Numeral v) :: env, envlist) tl)
 
74
    | Some (p, ETConstrList _) :: tl ->
 
75
        Gramext.action (fun (v:constr_expr list) -> make (env, v::envlist) tl)
 
76
    | Some (p, ETPattern) :: tl -> 
 
77
        failwith "Unexpected entry of type cases pattern" in
 
78
  make ([],[]) (List.rev pil)
 
79
 
 
80
let make_cases_pattern_action
 
81
  (f : loc -> cases_pattern_expr action_env -> cases_pattern_expr) pil =
 
82
  let rec make (env,envlist as fullenv : cases_pattern_expr action_env) = function
 
83
    | [] ->
 
84
        Gramext.action (fun loc -> f loc fullenv)
 
85
    | None :: tl -> (* parse a non-binding item *)
 
86
        Gramext.action (fun _ -> make fullenv tl)
 
87
    | Some (p, ETConstr _) :: tl -> (* pattern non-terminal *)
 
88
        Gramext.action (fun (v:cases_pattern_expr) -> make (v::env,envlist) tl)
 
89
    | Some (p, ETReference) :: tl -> (* non-terminal *)
 
90
        Gramext.action (fun (v:reference) ->
 
91
          make (CPatAtom (dummy_loc,Some v) :: env, envlist) tl)
 
92
    | Some (p, ETIdent) :: tl -> (* non-terminal *)
 
93
        Gramext.action (fun (v:identifier) ->
 
94
          make 
 
95
            (CPatAtom (dummy_loc,Some (Ident (dummy_loc,v)))::env, envlist) tl)
 
96
    | Some (p, ETBigint) :: tl -> (* non-terminal *)
 
97
        Gramext.action (fun (v:Bigint.bigint) ->
 
98
          make (CPatPrim (dummy_loc,Numeral v) :: env, envlist) tl)
 
99
    | Some (p, ETConstrList _) :: tl ->
 
100
        Gramext.action (fun (v:cases_pattern_expr list) ->
 
101
          make (env, v :: envlist) tl)
 
102
    | Some (p, (ETPattern | ETOther _)) :: tl -> 
 
103
        failwith "Unexpected entry of type cases pattern or other" in
 
104
  make ([],[]) (List.rev pil)
 
105
 
 
106
let make_constr_prod_item univ assoc from forpat = function
 
107
  | Term tok -> (Gramext.Stoken tok, None)
 
108
  | NonTerm (nt, ovar) ->
 
109
      let eobj = symbol_of_production assoc from forpat nt in
 
110
      (eobj, ovar)
 
111
 
 
112
let prepare_empty_levels entry (pos,p4assoc,name,reinit) =
 
113
  grammar_extend entry pos reinit [(name, p4assoc, [])]
 
114
 
 
115
let pure_sublevels level symbs =
 
116
  map_succeed (function
 
117
  | Gramext.Snterml (_,n) when Some (int_of_string n) <> level ->
 
118
      int_of_string n
 
119
  | _ ->
 
120
      failwith "") symbs
 
121
 
 
122
let extend_constr (entry,level) (n,assoc) mkact forpat pt =
 
123
  let univ = get_univ "constr" in
 
124
  let pil = List.map (make_constr_prod_item univ assoc n forpat) pt in
 
125
  let (symbs,ntl) = List.split pil in
 
126
  let pure_sublevels = pure_sublevels level symbs in
 
127
  let needed_levels = register_empty_levels forpat pure_sublevels in
 
128
  let pos,p4assoc,name,reinit = find_position forpat assoc level in
 
129
  List.iter (prepare_empty_levels entry) needed_levels;
 
130
  grammar_extend entry pos reinit [(name, p4assoc, [symbs, mkact ntl])]
 
131
 
 
132
let extend_constr_notation (n,assoc,ntn,rule) =
 
133
  (* Add the notation in constr *)
 
134
  let mkact loc env = CNotation (loc,ntn,env) in
 
135
  let e = get_constr_entry false (ETConstr (n,())) in
 
136
  extend_constr e (ETConstr(n,()),assoc) (make_constr_action mkact) false rule;
 
137
  (* Add the notation in cases_pattern *)
 
138
  let mkact loc env = CPatNotation (loc,ntn,env) in
 
139
  let e = get_constr_entry true (ETConstr (n,())) in
 
140
  extend_constr e (ETConstr (n,()),assoc) (make_cases_pattern_action mkact)
 
141
    true rule
 
142
 
 
143
(**********************************************************************)
 
144
(** Making generic actions in type generic_argument                   *)
 
145
 
 
146
let make_generic_action
 
147
  (f:loc -> ('b * raw_generic_argument) list -> 'a) pil =
 
148
  let rec make env = function
 
149
    | [] -> 
 
150
        Gramext.action (fun loc -> f loc env)
 
151
    | None :: tl -> (* parse a non-binding item *)
 
152
        Gramext.action (fun _ -> make env tl)
 
153
    | Some (p, t) :: tl -> (* non-terminal *)
 
154
        Gramext.action (fun v -> make ((p,in_generic t v) :: env) tl) in
 
155
  make [] (List.rev pil)
 
156
 
 
157
let make_rule univ f g pt =
 
158
  let (symbs,ntl) = List.split (List.map g pt) in
 
159
  let act = make_generic_action f ntl in
 
160
  (symbs, act)
 
161
 
 
162
(**********************************************************************)
 
163
(** Grammar extensions declared at ML level                           *) 
 
164
 
 
165
type grammar_tactic_production =
 
166
  | TacTerm of string
 
167
  | TacNonTerm of
 
168
      loc * (Gram.te Gramext.g_symbol * argument_type) * string option
 
169
 
 
170
let make_prod_item = function
 
171
  | TacTerm s -> (Gramext.Stoken (Lexer.terminal s), None)
 
172
  | TacNonTerm (_,(nont,t), po) -> (nont, Option.map (fun p -> (p,t)) po)
 
173
 
 
174
(* Tactic grammar extensions *)
 
175
 
 
176
let tac_exts = ref []
 
177
let get_extend_tactic_grammars () = !tac_exts
 
178
 
 
179
let extend_tactic_grammar s gl =
 
180
  tac_exts := (s,gl) :: !tac_exts;
 
181
  let univ = get_univ "tactic" in
 
182
  let mkact loc l = Tacexpr.TacExtend (loc,s,List.map snd l) in
 
183
  let rules = List.map (make_rule univ mkact make_prod_item) gl in
 
184
  Gram.extend Tactic.simple_tactic None [(None, None, List.rev rules)]
 
185
 
 
186
(* Vernac grammar extensions *)
 
187
 
 
188
let vernac_exts = ref []
 
189
let get_extend_vernac_grammars () = !vernac_exts
 
190
 
 
191
let extend_vernac_command_grammar s gl =
 
192
  vernac_exts := (s,gl) :: !vernac_exts;
 
193
  let univ = get_univ "vernac" in
 
194
  let mkact loc l = VernacExtend (s,List.map snd l) in
 
195
  let rules = List.map (make_rule univ mkact make_prod_item) gl in
 
196
  Gram.extend Vernac_.command None [(None, None, List.rev rules)]
 
197
 
 
198
(**********************************************************************)
 
199
(** Grammar declaration for Tactic Notation (Coq level)               *) 
 
200
 
 
201
(* Interpretation of the grammar entry names *)
 
202
 
 
203
let find_index s t =
 
204
  let t,n = repr_ident (id_of_string t) in
 
205
  if s <> t or n = None then raise Not_found;
 
206
  Option.get n
 
207
 
 
208
let rec interp_entry_name up_level s =
 
209
  let l = String.length s in
 
210
  if l > 8 & String.sub s 0 3 = "ne_" & String.sub s (l-5) 5 = "_list" then
 
211
    let t, g = interp_entry_name up_level (String.sub s 3 (l-8)) in
 
212
    List1ArgType t, Gramext.Slist1 g
 
213
  else if l > 5 & String.sub s (l-5) 5 = "_list" then
 
214
    let t, g = interp_entry_name up_level (String.sub s 0 (l-5)) in
 
215
    List0ArgType t, Gramext.Slist0 g
 
216
  else if l > 4 & String.sub s (l-4) 4 = "_opt" then
 
217
    let t, g = interp_entry_name up_level (String.sub s 0 (l-4)) in
 
218
    OptArgType t, Gramext.Sopt g
 
219
  else
 
220
    let s = if s = "hyp" then "var" else s in
 
221
    try 
 
222
      let i = find_index "tactic" s in
 
223
      ExtraArgType s, 
 
224
      if up_level<>5 && i=up_level then Gramext.Sself else
 
225
      if up_level<>5 && i=up_level-1 then Gramext.Snext else
 
226
      Gramext.Snterml(Pcoq.Gram.Entry.obj Tactic.tactic_expr,string_of_int i)
 
227
    with Not_found ->
 
228
    let e = 
 
229
      (* Qualified entries are no longer in use *)
 
230
      try get_entry (get_univ "tactic") s
 
231
      with _ -> 
 
232
      try get_entry (get_univ "prim") s
 
233
      with _ ->
 
234
      try get_entry (get_univ "constr") s
 
235
      with _ -> error ("Unknown entry "^s^".")
 
236
    in
 
237
    let o = object_of_typed_entry e in
 
238
    let t = type_of_typed_entry e in
 
239
    t,Gramext.Snterm (Pcoq.Gram.Entry.obj o)
 
240
 
 
241
let make_vprod_item n = function
 
242
  | VTerm s -> (Gramext.Stoken (Lexer.terminal s), None)
 
243
  | VNonTerm (loc, nt, po) ->
 
244
      let (etyp, e) = interp_entry_name n nt in
 
245
      e, Option.map (fun p -> (p,etyp)) po
 
246
 
 
247
let get_tactic_entry n =
 
248
  if n = 0 then
 
249
    weaken_entry Tactic.simple_tactic, None
 
250
  else if n = 5 then
 
251
    weaken_entry Tactic.binder_tactic, None
 
252
  else if 1<=n && n<5 then
 
253
    weaken_entry Tactic.tactic_expr, Some (Gramext.Level (string_of_int n))
 
254
  else 
 
255
    error ("Invalid Tactic Notation level: "^(string_of_int n)^".")
 
256
 
 
257
(* Declaration of the tactic grammar rule *)
 
258
 
 
259
let head_is_ident = function VTerm _::_ -> true | _ -> false
 
260
 
 
261
let add_tactic_entry (key,lev,prods,tac) =
 
262
  let univ = get_univ "tactic" in
 
263
  let entry, pos = get_tactic_entry lev in
 
264
  let mkprod = make_vprod_item lev in
 
265
  let rules = 
 
266
    if lev = 0 then begin
 
267
      if not (head_is_ident prods) then
 
268
        error "Notation for simple tactic must start with an identifier.";
 
269
      let mkact s tac loc l =
 
270
        (TacAlias(loc,s,l,tac):raw_atomic_tactic_expr) in
 
271
      make_rule univ (mkact key tac) mkprod prods
 
272
    end
 
273
    else
 
274
      let mkact s tac loc l = 
 
275
        (TacAtom(loc,TacAlias(loc,s,l,tac)):raw_tactic_expr) in
 
276
      make_rule univ (mkact key tac) mkprod prods in
 
277
  synchronize_level_positions ();
 
278
  grammar_extend entry pos None [(None, None, List.rev [rules])]
 
279
 
 
280
(**********************************************************************)
 
281
(** State of the grammar extensions                                   *)
 
282
 
 
283
type notation_grammar = 
 
284
    int * Gramext.g_assoc option * notation * prod_item list
 
285
 
 
286
type all_grammar_command =
 
287
  | Notation of Notation.level * notation_grammar
 
288
  | TacticGrammar of
 
289
      (string * int * grammar_production list * 
 
290
        (Names.dir_path * Tacexpr.glob_tactic_expr))
 
291
 
 
292
let (grammar_state : all_grammar_command list ref) = ref []
 
293
 
 
294
let extend_grammar gram =
 
295
  (match gram with
 
296
  | Notation (_,a) -> extend_constr_notation a
 
297
  | TacticGrammar g -> add_tactic_entry g);
 
298
  grammar_state := gram :: !grammar_state
 
299
 
 
300
let reset_extend_grammars_v8 () =
 
301
  let te = List.rev !tac_exts in
 
302
  let tv = List.rev !vernac_exts in
 
303
  tac_exts := [];
 
304
  vernac_exts := [];
 
305
  List.iter (fun (s,gl) -> print_string ("Resinstalling "^s); flush stdout; extend_tactic_grammar s gl) te;
 
306
  List.iter (fun (s,gl) -> extend_vernac_command_grammar s gl) tv
 
307
 
 
308
let recover_notation_grammar ntn prec =
 
309
  let l = map_succeed (function
 
310
    | Notation (prec',(_,_,ntn',_ as x)) when prec = prec' & ntn = ntn' -> x
 
311
    | _ -> failwith "") !grammar_state in
 
312
  assert (List.length l = 1);
 
313
  List.hd l
 
314
 
 
315
(* Summary functions: the state of the lexer is included in that of the parser.
 
316
   Because the grammar affects the set of keywords when adding or removing
 
317
   grammar rules. *)
 
318
type frozen_t = all_grammar_command list * Lexer.frozen_t
 
319
 
 
320
let freeze () = (!grammar_state, Lexer.freeze ())
 
321
 
 
322
(* We compare the current state of the grammar and the state to unfreeze, 
 
323
   by computing the longest common suffixes *)
 
324
let factorize_grams l1 l2 =
 
325
  if l1 == l2 then ([], [], l1) else list_share_tails l1 l2
 
326
 
 
327
let number_of_entries gcl =
 
328
  List.fold_left
 
329
    (fun n -> function
 
330
      | Notation _ -> n + 2 (* 1 for operconstr, 1 for pattern *)
 
331
      | TacticGrammar _ -> n + 1)
 
332
    0 gcl
 
333
 
 
334
let unfreeze (grams, lex) =
 
335
  let (undo, redo, common) = factorize_grams !grammar_state grams in
 
336
  let n = number_of_entries undo in
 
337
  remove_grammars n;
 
338
  remove_levels n;
 
339
  grammar_state := common;
 
340
  Lexer.unfreeze lex;
 
341
  List.iter extend_grammar (List.rev redo)
 
342
 
 
343
let init_grammar () =
 
344
  remove_grammars (number_of_entries !grammar_state);
 
345
  grammar_state := []
 
346
 
 
347
let init () =
 
348
  init_grammar ()
 
349
 
 
350
open Summary
 
351
 
 
352
let _ = 
 
353
  declare_summary "GRAMMAR_LEXER"
 
354
    { freeze_function = freeze;
 
355
      unfreeze_function = unfreeze;
 
356
      init_function = init;
 
357
      survive_module = false;
 
358
      survive_section = false }