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

« back to all changes in this revision

Viewing changes to tools/coqdoc/pretty.mll

  • 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
(* -*- compile-command: "make -C ../.. bin/coqdoc" -*- *)
 
2
(************************************************************************)
 
3
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
4
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
5
(*   \VV/  **************************************************************)
 
6
(*    //   *      This file is distributed under the terms of the       *)
 
7
(*         *       GNU Lesser General Public License Version 2.1        *)
 
8
(************************************************************************)
 
9
 
 
10
(*i $Id: pretty.mll 12187 2009-06-13 19:36:59Z msozeau $ i*)
 
11
 
 
12
(*s Utility functions for the scanners *)
 
13
 
 
14
{
 
15
  open Printf
 
16
  open Lexing 
 
17
 
 
18
  (* count the number of spaces at the beginning of a string *)
 
19
  let count_spaces s =
 
20
    let n = String.length s in
 
21
    let rec count c i = 
 
22
      if i == n then c,i else match s.[i] with
 
23
        | '\t' -> count (c + (8 - (c mod 8))) (i + 1)
 
24
        | ' ' -> count (c + 1) (i + 1)
 
25
        | _ -> c,i
 
26
    in
 
27
      count 0 0
 
28
 
 
29
  let count_dashes s =
 
30
    let c = ref 0 in
 
31
    for i = 0 to String.length s - 1 do if s.[i] = '-' then incr c done;
 
32
    !c
 
33
 
 
34
  let cut_head_tail_spaces s =
 
35
    let n = String.length s in
 
36
    let rec look_up i = if i == n || s.[i] <> ' ' then i else look_up (i+1) in
 
37
    let rec look_dn i = if i == -1 || s.[i] <> ' ' then i else look_dn (i-1) in
 
38
    let l = look_up 0 in
 
39
    let r = look_dn (n-1) in
 
40
    if l <= r then String.sub s l (r-l+1) else s
 
41
 
 
42
  let sec_title s =
 
43
    let rec count lev i = 
 
44
      if s.[i] = '*' then 
 
45
        count (succ lev) (succ i) 
 
46
      else 
 
47
        let t = String.sub s i (String.length s - i) in
 
48
        lev, cut_head_tail_spaces t
 
49
    in
 
50
    count 0 (String.index s '*')
 
51
 
 
52
  let strip_eol s =
 
53
    let eol = s.[String.length s - 1] = '\n' in
 
54
    (eol, if eol then String.sub s 1 (String.length s - 1) else s)
 
55
 
 
56
 
 
57
  let formatted = ref false
 
58
  let brackets = ref 0
 
59
  let comment_level = ref 0
 
60
  let in_proof = ref None
 
61
 
 
62
  let backtrack lexbuf = lexbuf.lex_curr_pos <- lexbuf.lex_start_pos
 
63
 
 
64
  let is_space = function ' ' | '\t' | '\n' | '\r' -> true | _ -> false
 
65
 
 
66
  (* saving/restoring the PP state *)
 
67
 
 
68
  type state = {
 
69
    st_gallina : bool;
 
70
    st_light : bool
 
71
  }
 
72
 
 
73
  let state_stack = Stack.create ()
 
74
 
 
75
  let save_state () = 
 
76
    Stack.push { st_gallina = !Cdglobals.gallina; st_light = !Cdglobals.light } state_stack
 
77
 
 
78
  let restore_state () =
 
79
    let s = Stack.pop state_stack in
 
80
    Cdglobals.gallina := s.st_gallina;
 
81
    Cdglobals.light := s.st_light
 
82
      
 
83
  let without_ref r f x = save_state (); r := false; f x; restore_state ()
 
84
 
 
85
  let without_gallina = without_ref Cdglobals.gallina
 
86
 
 
87
  let without_light = without_ref Cdglobals.light
 
88
 
 
89
  let show_all f = without_gallina (without_light f)
 
90
 
 
91
  let begin_show () = save_state (); Cdglobals.gallina := false; Cdglobals.light := false
 
92
  let end_show () = restore_state ()
 
93
 
 
94
  (* Reset the globals *)
 
95
 
 
96
  let reset () =
 
97
    formatted := false;
 
98
    brackets := 0;
 
99
    comment_level := 0
 
100
 
 
101
  (* erasing of Section/End *)
 
102
 
 
103
  let section_re = Str.regexp "[ \t]*Section"
 
104
  let end_re = Str.regexp "[ \t]*End"
 
105
  let is_section s = Str.string_match section_re s 0
 
106
  let is_end s = Str.string_match end_re s 0
 
107
 
 
108
  let sections_to_close = ref 0
 
109
 
 
110
  let section_or_end s =
 
111
    if is_section s then begin
 
112
      incr sections_to_close; true
 
113
    end else if is_end s then begin
 
114
      if !sections_to_close > 0 then begin 
 
115
        decr sections_to_close; true 
 
116
      end else 
 
117
        false
 
118
    end else
 
119
      true
 
120
 
 
121
  (* tokens pretty-print *)
 
122
 
 
123
  let token_buffer = Buffer.create 1024
 
124
 
 
125
  let token_re = 
 
126
    Str.regexp "[ \t]*(\\*\\*[ \t]+printing[ \t]+\\([^ \t]+\\)"
 
127
  let printing_token_re =
 
128
    Str.regexp
 
129
      "[ \t]*\\(\\(%\\([^%]*\\)%\\)\\|\\(\\$[^$]*\\$\\)\\)?[ \t]*\\(#\\(\\([^#]\\|&#\\)*\\)#\\)?"
 
130
 
 
131
  let add_printing_token toks pps =
 
132
    try
 
133
      if Str.string_match token_re toks 0 then
 
134
        let tok = Str.matched_group 1 toks in
 
135
        if Str.string_match printing_token_re pps 0 then
 
136
          let pp = 
 
137
            (try Some (Str.matched_group 3 pps) with _ -> 
 
138
             try Some (Str.matched_group 4 pps) with _ -> None),
 
139
            (try Some (Str.matched_group 6 pps) with _ -> None)
 
140
          in
 
141
          Output.add_printing_token tok pp
 
142
    with _ ->
 
143
      ()
 
144
 
 
145
  let remove_token_re = 
 
146
    Str.regexp 
 
147
      "[ \t]*(\\*\\*[ \t]+remove[ \t]+printing[ \t]+\\([^ \t]+\\)[ \t]*\\*)"
 
148
 
 
149
  let remove_printing_token toks =
 
150
    try
 
151
      if Str.string_match remove_token_re toks 0 then
 
152
        let tok = Str.matched_group 1 toks in
 
153
        Output.remove_printing_token tok
 
154
    with _ ->
 
155
      ()
 
156
 
 
157
  let extract_ident_re = Str.regexp "([ \t]*\\([^ \t]+\\)[ \t]*:="
 
158
  let extract_ident s =
 
159
    assert (String.length s >= 3);
 
160
    if Str.string_match extract_ident_re s 0 then
 
161
      Str.matched_group 1 s
 
162
    else
 
163
      String.sub s 1 (String.length s - 3)
 
164
 
 
165
  let symbol lexbuf s = Output.symbol s 
 
166
 
 
167
}
 
168
 
 
169
(*s Regular expressions *)
 
170
 
 
171
let space = [' ' '\t']
 
172
let space_nl = [' ' '\t' '\n' '\r']
 
173
let nl = "\r\n" | '\n'
 
174
 
 
175
let firstchar = 
 
176
  ['A'-'Z' 'a'-'z' '_' 
 
177
  (* iso 8859-1 accents *) 
 
178
  '\192'-'\214' '\216'-'\246' '\248'-'\255' ] |
 
179
  (* *)
 
180
  '\194' '\185' |
 
181
  (* utf-8 latin 1 supplement *) 
 
182
  '\195' ['\128'-'\191'] |
 
183
  (* utf-8 letterlike symbols *) 
 
184
  '\206' ('\160' | [ '\177'-'\183'] | '\187') |
 
185
  '\226' ('\130' [ '\128'-'\137' ] (* subscripts *)
 
186
    | '\129' [ '\176'-'\187' ] (* superscripts *)
 
187
    | '\132' ['\128'-'\191'] | '\133' ['\128'-'\143'])
 
188
let identchar = 
 
189
  firstchar | ['\'' '0'-'9' '@' ]
 
190
let id = firstchar identchar*
 
191
let pfx_id = (id '.')*
 
192
let identifier = 
 
193
  id | pfx_id id
 
194
 
 
195
let symbolchar_symbol_no_brackets =
 
196
  ['!' '$' '%' '&' '*' '+' ',' '^' '#'
 
197
      '\\' '/' '-' '<' '>' '|' ':' '?' '=' '~' ] |
 
198
  (* utf-8 symbols *) 
 
199
  '\226' ['\134'-'\143' '\152'-'\155' '\164'-'\165' '\168'-'\171'] _
 
200
let symbolchar_no_brackets = symbolchar_symbol_no_brackets | 
 
201
    [ '@' '{' '}' '(' ')' 'A'-'Z' 'a'-'z' '_']
 
202
let symbolchar = symbolchar_no_brackets | '[' | ']'
 
203
let token_no_brackets = symbolchar_symbol_no_brackets symbolchar_no_brackets*
 
204
let token = symbolchar_symbol_no_brackets symbolchar* | '[' [^ '[' ']' ':']* ']'
 
205
let printing_token = (token | id)+
 
206
 
 
207
(* tokens with balanced brackets *)
 
208
let token_brackets =
 
209
  ( token_no_brackets ('[' token_no_brackets? ']')* 
 
210
  | token_no_brackets? ('[' token_no_brackets? ']')+ )
 
211
  token_no_brackets?
 
212
 
 
213
let thm_token = 
 
214
  "Theorem" 
 
215
  | "Lemma" 
 
216
  | "Fact" 
 
217
  | "Remark" 
 
218
  | "Corollary" 
 
219
  | "Proposition" 
 
220
  | "Property"
 
221
  | "Goal"
 
222
 
 
223
let prf_token =
 
224
  "Next" space+ "Obligation"
 
225
  | "Proof" (space* "." | space+ "with")
 
226
 
 
227
let def_token = 
 
228
  "Definition" 
 
229
  | "Let" 
 
230
  | "Class"
 
231
  | "SubClass"
 
232
  | "Example"
 
233
  | "Local" 
 
234
  | "Fixpoint" 
 
235
  | "Boxed" 
 
236
  | "CoFixpoint" 
 
237
  | "Record" 
 
238
  | "Structure" 
 
239
  | "Scheme"
 
240
  | "Inductive"
 
241
  | "CoInductive"
 
242
  | "Equations"
 
243
  | "Instance"
 
244
  | "Global" space+ "Instance"
 
245
 
 
246
let decl_token = 
 
247
  "Hypothesis" 
 
248
  | "Hypotheses" 
 
249
  | "Parameter" 
 
250
  | "Axiom" 's'? 
 
251
  | "Conjecture"
 
252
 
 
253
let gallina_ext =
 
254
  "Module" 
 
255
  | "Include" space+ "Type"
 
256
  | "Include"
 
257
  | "Declare" space+ "Module"
 
258
  | "Transparent"
 
259
  | "Opaque"
 
260
  | "Canonical"
 
261
  | "Coercion"
 
262
  | "Identity"
 
263
  | "Implicit"
 
264
  | "Notation"
 
265
  | "Infix"
 
266
  | "Tactic" space+ "Notation"
 
267
  | "Reserved" space+ "Notation"
 
268
  | "Section"
 
269
  | "Context"
 
270
  | "Variable" 's'?
 
271
  | ("Hypothesis" | "Hypotheses")
 
272
  | "End"
 
273
 
 
274
let commands = 
 
275
  "Pwd"
 
276
  | "Cd"
 
277
  | "Drop"
 
278
  | "ProtectedLoop"
 
279
  | "Quit"
 
280
  | "Load"
 
281
  | "Add"
 
282
  | "Remove" space+ "Loadpath"
 
283
  | "Print"
 
284
  | "Inspect"
 
285
  | "About"
 
286
  | "Search"
 
287
  | "Eval"
 
288
  | "Reset"
 
289
  | "Check"
 
290
  | "Type"
 
291
 
 
292
  | "Section"
 
293
  | "Chapter"
 
294
  | "Variable" 's'?
 
295
  | ("Hypothesis" | "Hypotheses")
 
296
  | "End"
 
297
 
 
298
let end_kw = "Qed" | "Defined" | "Save" | "Admitted" | "Abort"
 
299
 
 
300
let extraction = 
 
301
  "Extraction"
 
302
  | "Recursive" space+ "Extraction" 
 
303
  | "Extract"
 
304
 
 
305
let gallina_kw = thm_token | def_token | decl_token | gallina_ext | commands | extraction
 
306
 
 
307
let prog_kw =
 
308
  "Program" space+ gallina_kw
 
309
  | "Obligation"
 
310
  | "Obligations"
 
311
  | "Solve"
 
312
 
 
313
let gallina_kw_to_hide =
 
314
    "Implicit" space+ "Arguments"
 
315
  | "Ltac"
 
316
  | "Require"
 
317
  | "Import"
 
318
  | "Export"
 
319
  | "Load" 
 
320
  | "Hint"
 
321
  | "Open"
 
322
  | "Close"
 
323
  | "Delimit"
 
324
  | "Transparent"
 
325
  | "Opaque"
 
326
  | ("Declare" space+ ("Morphism" | "Step") )
 
327
  | ("Set" | "Unset") space+ "Printing" space+ "Coercions"
 
328
  | "Declare" space+ ("Left" | "Right") space+ "Step" 
 
329
 
 
330
 
 
331
let section = "*" | "**" | "***" | "****"
 
332
 
 
333
let item_space = "    "
 
334
 
 
335
let begin_hide = "(*" space* "begin" space+ "hide" space* "*)" space* nl
 
336
let end_hide = "(*" space* "end" space+ "hide" space* "*)" space* nl
 
337
let begin_show = "(*" space* "begin" space+ "show" space* "*)" space* nl
 
338
let end_show = "(*" space* "end" space+ "show" space* "*)" space* nl
 
339
(*
 
340
let begin_verb = "(*" space* "begin" space+ "verb" space* "*)"
 
341
let end_verb = "(*" space* "end" space+ "verb" space* "*)"
 
342
*)
 
343
 
 
344
 
 
345
 
 
346
(*s Scanning Coq, at beginning of line *)
 
347
 
 
348
rule coq_bol = parse
 
349
  | space* nl+
 
350
      { if not (!in_proof <> None && (!Cdglobals.gallina || !Cdglobals.light)) then Output.empty_line_of_code (); coq_bol lexbuf }
 
351
  | space* "(**" space_nl
 
352
      { Output.end_coq (); Output.start_doc (); 
 
353
        let eol = doc_bol lexbuf in
 
354
          Output.end_doc (); Output.start_coq (); 
 
355
          if eol then coq_bol lexbuf else coq lexbuf }
 
356
  | space* "Comments" space_nl
 
357
      { Output.end_coq (); Output.start_doc (); comments lexbuf; Output.end_doc (); 
 
358
        Output.start_coq (); coq lexbuf }
 
359
  | space* begin_hide
 
360
      { skip_hide lexbuf; coq_bol lexbuf }
 
361
  | space* begin_show
 
362
      { begin_show (); coq_bol lexbuf }
 
363
  | space* end_show
 
364
      { end_show (); coq_bol lexbuf }
 
365
  | space* gallina_kw_to_hide
 
366
      { let s = lexeme lexbuf in
 
367
          if !Cdglobals.light && section_or_end s then 
 
368
            let eol = skip_to_dot lexbuf in
 
369
              if eol then (coq_bol lexbuf) else coq lexbuf
 
370
          else 
 
371
            begin
 
372
              let nbsp,isp = count_spaces s in
 
373
                Output.indentation nbsp; 
 
374
                let s = String.sub s isp (String.length s - isp) in
 
375
                  Output.ident s (lexeme_start lexbuf + isp); 
 
376
                  let eol = body lexbuf in 
 
377
                    if eol then coq_bol lexbuf else coq lexbuf
 
378
            end }
 
379
  | space* thm_token
 
380
      { let s = lexeme lexbuf in 
 
381
        let nbsp,isp = count_spaces s in
 
382
        let s = String.sub s isp (String.length s - isp)  in
 
383
          Output.indentation nbsp;
 
384
          Output.ident s (lexeme_start lexbuf + isp); 
 
385
          let eol = body lexbuf in
 
386
            in_proof := Some eol;
 
387
            if eol then coq_bol lexbuf else coq lexbuf }
 
388
  | space* prf_token
 
389
      { in_proof := Some true;
 
390
        let eol = 
 
391
          if not !Cdglobals.gallina then 
 
392
            begin backtrack lexbuf; body_bol lexbuf end 
 
393
          else 
 
394
            let s = lexeme lexbuf in
 
395
              if s.[String.length s - 1] = '.' then false
 
396
              else skip_to_dot lexbuf
 
397
        in if eol then coq_bol lexbuf else coq lexbuf }
 
398
  | space* end_kw { 
 
399
      let eol = 
 
400
        if not (!in_proof <> None && !Cdglobals.gallina) then 
 
401
          begin backtrack lexbuf; body_bol lexbuf end 
 
402
        else skip_to_dot lexbuf
 
403
      in
 
404
        in_proof := None;
 
405
        if eol then coq_bol lexbuf else coq lexbuf }
 
406
  | space* gallina_kw
 
407
      { 
 
408
        in_proof := None;
 
409
        let s = lexeme lexbuf in 
 
410
        let nbsp,isp = count_spaces s in
 
411
        let s = String.sub s isp (String.length s - isp)  in
 
412
          Output.indentation nbsp;
 
413
          Output.ident s (lexeme_start lexbuf + isp); 
 
414
          let eol= body lexbuf in
 
415
            if eol then coq_bol lexbuf else coq lexbuf }
 
416
  | space* prog_kw
 
417
      { 
 
418
        in_proof := None;
 
419
        let s = lexeme lexbuf in 
 
420
        let nbsp,isp = count_spaces s in
 
421
          Output.indentation nbsp;
 
422
          let s = String.sub s isp (String.length s - isp)  in
 
423
            Output.ident s (lexeme_start lexbuf + isp); 
 
424
            let eol= body lexbuf in
 
425
              if eol then coq_bol lexbuf else coq lexbuf }
 
426
 
 
427
  | space* "(**" space+ "printing" space+ printing_token space+
 
428
      { let tok = lexeme lexbuf in
 
429
        let s = printing_token_body lexbuf in
 
430
          add_printing_token tok s;
 
431
          coq_bol lexbuf }
 
432
  | space* "(**" space+ "printing" space+
 
433
      { eprintf "warning: bad 'printing' command at character %d\n" 
 
434
          (lexeme_start lexbuf); flush stderr;
 
435
        comment_level := 1;
 
436
        ignore (comment lexbuf);
 
437
        coq_bol lexbuf }
 
438
  | space* "(**" space+ "remove" space+ "printing" space+ 
 
439
      (identifier | token) space* "*)"
 
440
      { remove_printing_token (lexeme lexbuf);
 
441
        coq_bol lexbuf }
 
442
  | space* "(**" space+ "remove" space+ "printing" space+
 
443
      { eprintf "warning: bad 'remove printing' command at character %d\n" 
 
444
          (lexeme_start lexbuf); flush stderr;
 
445
        comment_level := 1;
 
446
        ignore (comment lexbuf);
 
447
        coq_bol lexbuf }
 
448
  | space* "(*"
 
449
      { comment_level := 1; 
 
450
        if !Cdglobals.parse_comments then begin
 
451
          let s = lexeme lexbuf in 
 
452
          let nbsp,isp = count_spaces s in
 
453
            Output.indentation nbsp;
 
454
            Output.start_comment ();
 
455
        end;
 
456
        let eol = comment lexbuf in
 
457
          if eol then coq_bol lexbuf else coq lexbuf }
 
458
  | eof 
 
459
      { () }
 
460
  | _
 
461
      { let eol = 
 
462
          if not !Cdglobals.gallina then 
 
463
            begin backtrack lexbuf; body_bol lexbuf end 
 
464
          else 
 
465
            skip_to_dot lexbuf 
 
466
        in
 
467
          if eol then coq_bol lexbuf else coq lexbuf }
 
468
 
 
469
(*s Scanning Coq elsewhere *)
 
470
 
 
471
and coq = parse
 
472
  | nl 
 
473
      { if not (!in_proof <> None && !Cdglobals.gallina) then Output.line_break(); coq_bol lexbuf }
 
474
  | "(**" space_nl
 
475
      { Output.end_coq (); Output.start_doc (); 
 
476
        let eol = doc_bol lexbuf in
 
477
          Output.end_doc (); Output.start_coq (); 
 
478
          if eol then coq_bol lexbuf else coq lexbuf }
 
479
  | "(*"
 
480
      { comment_level := 1;
 
481
        if !Cdglobals.parse_comments then begin
 
482
          let s = lexeme lexbuf in 
 
483
          let nbsp,isp = count_spaces s in
 
484
            Output.indentation nbsp;
 
485
            Output.start_comment ();
 
486
        end;
 
487
        let eol = comment lexbuf in
 
488
          if eol then coq_bol lexbuf
 
489
          else coq lexbuf
 
490
      }
 
491
  | nl+ space* "]]"
 
492
      { if not !formatted then begin symbol lexbuf (lexeme lexbuf); coq lexbuf end }
 
493
  | eof 
 
494
      { () }
 
495
  | gallina_kw_to_hide
 
496
      { let s = lexeme lexbuf in
 
497
          if !Cdglobals.light && section_or_end s then 
 
498
            begin 
 
499
              let eol = skip_to_dot lexbuf in
 
500
                if eol then coq_bol lexbuf else coq lexbuf 
 
501
            end 
 
502
          else 
 
503
            begin
 
504
              Output.ident s (lexeme_start lexbuf); 
 
505
              let eol=body lexbuf in 
 
506
                if eol then coq_bol lexbuf else coq lexbuf
 
507
            end }
 
508
  | prf_token
 
509
      { let eol = 
 
510
          if not !Cdglobals.gallina then 
 
511
            begin backtrack lexbuf; body_bol lexbuf end 
 
512
          else 
 
513
            let s = lexeme lexbuf in
 
514
            let eol = 
 
515
              if s.[String.length s - 1] = '.' then false
 
516
              else skip_to_dot lexbuf
 
517
            in
 
518
              eol
 
519
        in if eol then coq_bol lexbuf else coq lexbuf }
 
520
  | end_kw { 
 
521
      let eol = 
 
522
        if not !Cdglobals.gallina then 
 
523
          begin backtrack lexbuf; body lexbuf end 
 
524
        else 
 
525
          let eol = skip_to_dot lexbuf in
 
526
            if !in_proof <> Some true && eol then 
 
527
              Output.line_break ();
 
528
            eol
 
529
      in
 
530
        in_proof := None;
 
531
        if eol then coq_bol lexbuf else coq lexbuf }
 
532
  | gallina_kw
 
533
      { let s = lexeme lexbuf in 
 
534
          Output.ident s (lexeme_start lexbuf); 
 
535
        let eol = body lexbuf in
 
536
          if eol then coq_bol lexbuf else coq lexbuf }
 
537
  | prog_kw
 
538
      { let s = lexeme lexbuf in 
 
539
          Output.ident s (lexeme_start lexbuf); 
 
540
        let eol = body lexbuf in
 
541
          if eol then coq_bol lexbuf else coq lexbuf }
 
542
  | space+ { Output.char ' '; coq lexbuf }
 
543
  | eof 
 
544
      { () }
 
545
  | _ { let eol = 
 
546
          if not !Cdglobals.gallina then 
 
547
            begin backtrack lexbuf; body lexbuf end 
 
548
          else 
 
549
            skip_to_dot lexbuf
 
550
        in 
 
551
          if eol then coq_bol lexbuf else coq lexbuf}
 
552
      
 
553
(*s Scanning documentation, at beginning of line *)
 
554
 
 
555
and doc_bol = parse
 
556
  | space* nl+
 
557
      { Output.paragraph (); doc_bol lexbuf }
 
558
  | space* section space+ ([^'\n' '*'] | '*'+ [^'\n' ')' '*'])* ('*'+ '\n')?
 
559
      { let eol, lex = strip_eol (lexeme lexbuf) in
 
560
        let lev, s = sec_title lex in
 
561
          Output.section lev (fun () -> ignore (doc (from_string s)));
 
562
          if eol then doc_bol lexbuf else doc lexbuf }
 
563
  | space* '-'+
 
564
      { let n = count_dashes (lexeme lexbuf) in
 
565
        if n >= 4 then Output.rule () else Output.item n;
 
566
        doc lexbuf }
 
567
  | "<<" space*
 
568
      { Output.start_verbatim (); verbatim lexbuf; doc_bol lexbuf }
 
569
  | eof 
 
570
      { true }
 
571
  | _ 
 
572
      { backtrack lexbuf; doc lexbuf }
 
573
 
 
574
(*s Scanning documentation elsewhere *)
 
575
 
 
576
and doc = parse
 
577
  | nl
 
578
      { Output.char '\n'; doc_bol lexbuf }
 
579
  | "[[" nl
 
580
      { formatted := true; Output.line_break (); Output.start_inline_coq ();
 
581
        let eol = body_bol lexbuf in 
 
582
          Output.end_inline_coq (); formatted := false;
 
583
          if eol then doc_bol lexbuf else doc lexbuf}
 
584
  | "["
 
585
      { brackets := 1; 
 
586
        Output.start_inline_coq (); escaped_coq lexbuf; Output.end_inline_coq ();
 
587
        doc lexbuf }
 
588
  | '*'* "*)" space* nl
 
589
      { true }
 
590
  | '*'* "*)"
 
591
      { false }
 
592
  | "$"
 
593
      { Output.start_latex_math (); escaped_math_latex lexbuf; doc lexbuf }
 
594
  | "$$"
 
595
      { Output.char '$'; doc lexbuf }
 
596
  | "%"
 
597
      { escaped_latex lexbuf; doc lexbuf }
 
598
  | "%%"
 
599
      { Output.char '%'; doc lexbuf }
 
600
  | "#"
 
601
      { escaped_html lexbuf; doc lexbuf }
 
602
  | "##"
 
603
      { Output.char '#'; doc lexbuf }
 
604
  | eof 
 
605
      { false }
 
606
  | _ 
 
607
      { Output.char (lexeme_char lexbuf 0); doc lexbuf }
 
608
 
 
609
(*s Various escapings *)
 
610
 
 
611
and escaped_math_latex = parse
 
612
  | "$" { Output.stop_latex_math () }
 
613
  | eof { Output.stop_latex_math () }
 
614
  | _   { Output.latex_char (lexeme_char lexbuf 0); escaped_math_latex lexbuf }
 
615
 
 
616
and escaped_latex = parse
 
617
  | "%" { () }
 
618
  | eof { () }
 
619
  | _   { Output.latex_char (lexeme_char lexbuf 0); escaped_latex lexbuf }
 
620
 
 
621
and escaped_html = parse
 
622
  | "#" { () }
 
623
  | "&#"
 
624
        { Output.html_char '&'; Output.html_char '#'; escaped_html lexbuf }
 
625
  | "##"
 
626
        { Output.html_char '#'; escaped_html lexbuf }
 
627
  | eof { () }
 
628
  | _   { Output.html_char (lexeme_char lexbuf 0); escaped_html lexbuf }
 
629
 
 
630
and verbatim = parse
 
631
  | nl ">>" { Output.verbatim_char '\n'; Output.stop_verbatim () }
 
632
  | eof { Output.stop_verbatim () }
 
633
  | _ { Output.verbatim_char (lexeme_char lexbuf 0); verbatim lexbuf }
 
634
 
 
635
(*s Coq, inside quotations *)
 
636
 
 
637
and escaped_coq = parse
 
638
  | "]"
 
639
      { decr brackets; 
 
640
        if !brackets > 0 then begin Output.char ']'; escaped_coq lexbuf end }
 
641
  | "["
 
642
      { incr brackets; Output.char '['; escaped_coq lexbuf }
 
643
  | "(*"
 
644
      { comment_level := 1; ignore (comment lexbuf); escaped_coq lexbuf }
 
645
  | "*)"
 
646
      { (* likely to be a syntax error: we escape *) backtrack lexbuf }
 
647
  | eof
 
648
      { () }
 
649
  | token_brackets
 
650
      { let s = lexeme lexbuf in
 
651
          symbol lexbuf s; escaped_coq lexbuf }
 
652
  | (identifier '.')* identifier
 
653
      { Output.ident (lexeme lexbuf) (lexeme_start lexbuf); escaped_coq lexbuf }
 
654
  | _ 
 
655
      { Output.char (lexeme_char lexbuf 0); escaped_coq lexbuf }
 
656
 
 
657
(*s Coq "Comments" command. *)
 
658
 
 
659
and comments = parse
 
660
  | space_nl+ 
 
661
      { Output.char ' '; comments lexbuf }
 
662
  | '"' [^ '"']* '"' 
 
663
      { let s = lexeme lexbuf in
 
664
        let s = String.sub s 1 (String.length s - 2) in
 
665
        ignore (doc (from_string s)); comments lexbuf }
 
666
  | ([^ '.' '"'] | '.' [^ ' ' '\t' '\n'])+
 
667
      { escaped_coq (from_string (lexeme lexbuf)); comments lexbuf }
 
668
  | "." (space_nl | eof)
 
669
      { () }
 
670
  | eof 
 
671
      { () }
 
672
  | _   
 
673
      { Output.char (lexeme_char lexbuf 0); comments lexbuf }
 
674
 
 
675
(*s Skip comments *)
 
676
 
 
677
and comment = parse
 
678
  | "(*" { incr comment_level;
 
679
           if !Cdglobals.parse_comments then Output.start_comment ();
 
680
           comment lexbuf }
 
681
  | "*)" space* nl {
 
682
      if !Cdglobals.parse_comments then (Output.end_comment (); Output.line_break ());
 
683
      decr comment_level; if !comment_level > 0 then comment lexbuf else true }
 
684
  | "*)" { 
 
685
      if !Cdglobals.parse_comments then (Output.end_comment ());
 
686
      decr comment_level; if !comment_level > 0 then comment lexbuf else false }
 
687
  | "[" { 
 
688
      if !Cdglobals.parse_comments then (
 
689
        brackets := 1;
 
690
        Output.start_inline_coq (); escaped_coq lexbuf; Output.end_inline_coq ());
 
691
      comment lexbuf }
 
692
  | eof  { false }
 
693
  | space+ { if !Cdglobals.parse_comments then 
 
694
        Output.indentation (fst (count_spaces (lexeme lexbuf))); comment lexbuf }
 
695
  | nl   { if !Cdglobals.parse_comments then Output.line_break (); comment lexbuf }
 
696
  | _    { if !Cdglobals.parse_comments then Output.char (lexeme_char lexbuf 0);
 
697
  comment lexbuf }
 
698
      
 
699
and skip_to_dot = parse
 
700
  | '.' space* nl { true }
 
701
  | eof | '.' space+ { false }
 
702
  | "(*" { comment_level := 1; ignore (comment lexbuf); skip_to_dot lexbuf }
 
703
  | _ { skip_to_dot lexbuf }
 
704
 
 
705
and body_bol = parse
 
706
  | space+
 
707
      { Output.indentation (fst (count_spaces (lexeme lexbuf))); body lexbuf }
 
708
  | _ { backtrack lexbuf; Output.indentation 0; body lexbuf }
 
709
 
 
710
and body = parse
 
711
  | nl {Output.line_break(); body_bol lexbuf}
 
712
  | nl+ space* "]]"
 
713
      { if not !formatted then begin symbol lexbuf (lexeme lexbuf); body lexbuf end else true }
 
714
  | eof { false }
 
715
  | '.' space* nl | '.' space* eof 
 
716
        { Output.char '.'; Output.line_break(); 
 
717
          if not !formatted then true else body_bol lexbuf }      
 
718
  | '.' space+ { Output.char '.'; Output.char ' '; 
 
719
          if not !formatted then false else body lexbuf }
 
720
  | '"' { Output.char '"'; ignore(notation lexbuf); body lexbuf }
 
721
  | "(*" { comment_level := 1; 
 
722
           if !Cdglobals.parse_comments then Output.start_comment ();
 
723
           let eol = comment lexbuf in 
 
724
             if eol 
 
725
             then begin if not !Cdglobals.parse_comments then Output.line_break(); body_bol lexbuf end
 
726
             else body lexbuf }
 
727
  | identifier 
 
728
      { let s = lexeme lexbuf in 
 
729
          Output.ident s (lexeme_start lexbuf); 
 
730
          body lexbuf }
 
731
  | token_no_brackets
 
732
      { let s = lexeme lexbuf in
 
733
          symbol lexbuf s; body lexbuf }
 
734
  | _ { let c = lexeme_char lexbuf 0 in 
 
735
          Output.char c; 
 
736
          body lexbuf }
 
737
 
 
738
and notation_bol = parse
 
739
  | space+
 
740
      { Output.indentation (fst (count_spaces (lexeme lexbuf))); notation lexbuf }
 
741
  | _ { backtrack lexbuf; notation lexbuf }
 
742
 
 
743
and notation = parse
 
744
  | nl { Output.line_break(); notation_bol lexbuf }
 
745
  | '"' { Output.char '"'}
 
746
  | token
 
747
      { let s = lexeme lexbuf in
 
748
          symbol lexbuf s; notation lexbuf }
 
749
  | _ { let c = lexeme_char lexbuf 0 in 
 
750
          Output.char c; 
 
751
          notation lexbuf }
 
752
 
 
753
and skip_hide = parse
 
754
  | eof | end_hide { () }
 
755
  | _ { skip_hide lexbuf }
 
756
 
 
757
(*s Reading token pretty-print *)
 
758
 
 
759
and printing_token_body = parse
 
760
  | "*)" nl? | eof 
 
761
        { let s = Buffer.contents token_buffer in 
 
762
          Buffer.clear token_buffer;
 
763
          s }
 
764
  | _   { Buffer.add_string token_buffer (lexeme lexbuf); 
 
765
          printing_token_body lexbuf }
 
766
 
 
767
(*s Applying the scanners to files *)
 
768
 
 
769
{
 
770
 
 
771
  let coq_file f m =
 
772
    reset ();
 
773
    Index.current_library := m;
 
774
    Output.start_module ();
 
775
    let c = open_in f in
 
776
    let lb = from_channel c in
 
777
    Output.start_coq (); coq_bol lb; Output.end_coq ();
 
778
    close_in c
 
779
 
 
780
}
 
781