| 9139 |      1 | (*  Title:      Pure/Isar/thy_header.ML
 | 
|  |      2 |     ID:         $Id$
 | 
|  |      3 |     Author:     Markus Wenzel, TU Muenchen
 | 
|  |      4 | 
 | 
|  |      5 | Theory headers (old and new-style).
 | 
|  |      6 | *)
 | 
|  |      7 | 
 | 
|  |      8 | signature THY_HEADER =
 | 
|  |      9 | sig
 | 
|  |     10 |   val is_old: (string, 'a) Source.source * Position.T -> bool
 | 
|  |     11 |   val args: OuterLex.token list ->
 | 
|  |     12 |     (string * string list * (string * bool) list) * OuterLex.token list
 | 
|  |     13 |   val scan: (string, 'a) Source.source * Position.T -> string * string list * (string * bool) list
 | 
|  |     14 | end;
 | 
|  |     15 | 
 | 
|  |     16 | structure ThyHeader: THY_HEADER =
 | 
|  |     17 | struct
 | 
|  |     18 | 
 | 
|  |     19 | structure T = OuterLex;
 | 
|  |     20 | structure P = OuterParse;
 | 
|  |     21 | 
 | 
|  |     22 | 
 | 
|  |     23 | (* scan header *)
 | 
|  |     24 | 
 | 
|  |     25 | fun scan_header get_lex scan (src, pos) =
 | 
| 12840 |     26 |   let val res =
 | 
|  |     27 |     src
 | 
|  |     28 |     |> Symbol.source false
 | 
|  |     29 |     |> T.source false (fn () => (get_lex (), Scan.empty_lexicon)) pos
 | 
|  |     30 |     |> T.source_proper
 | 
| 15531 |     31 |     |> Source.source T.stopper (Scan.single scan) NONE
 | 
| 12840 |     32 |     |> Source.get_single;
 | 
|  |     33 |   in
 | 
| 15531 |     34 |     (case res of SOME (x, _) => x
 | 
|  |     35 |     | NONE => error ("Unexpected end of input" ^ Position.str_of pos))
 | 
| 12840 |     36 |   end;
 | 
| 9139 |     37 | 
 | 
|  |     38 | 
 | 
|  |     39 | (* keywords *)
 | 
|  |     40 | 
 | 
|  |     41 | val headerN = "header";
 | 
|  |     42 | val theoryN = "theory";
 | 
| 15141 |     43 | val importsN = "imports";
 | 
| 9139 |     44 | 
 | 
|  |     45 | val theory_keyword = P.$$$ theoryN;
 | 
|  |     46 | val header_keyword = P.$$$ headerN;
 | 
| 15141 |     47 | val imports_keyword = P.$$$ importsN;
 | 
| 9139 |     48 | 
 | 
|  |     49 | 
 | 
|  |     50 | (* detect new/old headers *)
 | 
|  |     51 | 
 | 
|  |     52 | val check_header_lexicon = T.make_lexicon [headerN, theoryN];
 | 
|  |     53 | val check_header = Scan.option (header_keyword || theory_keyword);
 | 
|  |     54 | 
 | 
|  |     55 | fun is_old src_pos =
 | 
|  |     56 |   Library.is_none (scan_header (K check_header_lexicon) check_header src_pos);
 | 
|  |     57 | 
 | 
|  |     58 | 
 | 
|  |     59 | (* scan old/new headers *)
 | 
|  |     60 | 
 | 
| 15132 |     61 | val header_lexicon = T.make_lexicon
 | 
| 15141 |     62 |   ["(", ")", "+", ":", ";", "=", "begin", "files", headerN, importsN, theoryN];
 | 
| 9139 |     63 | 
 | 
|  |     64 | val file_name =
 | 
|  |     65 |   (P.$$$ "(" |-- P.!!! (P.name --| P.$$$ ")")) >> rpair false || P.name >> rpair true;
 | 
|  |     66 | 
 | 
|  |     67 | val args =
 | 
| 15132 |     68 |   (P.name -- (P.$$$ "=" |-- P.enum1 "+" P.name ||
 | 
| 15141 |     69 |               imports_keyword |-- Scan.repeat1 P.name) --
 | 
| 15132 |     70 |     Scan.optional (P.$$$ "files" |-- P.!!! (Scan.repeat1 file_name)) [] --|
 | 
|  |     71 |   (P.$$$ ":" || P.$$$ "begin"))
 | 
| 9139 |     72 |   >> (fn ((A, Bs), files) => (A, Bs, files));
 | 
|  |     73 | 
 | 
|  |     74 | 
 | 
|  |     75 | val new_header =
 | 
|  |     76 |   header_keyword |-- (P.!!! (P.text -- Scan.repeat P.semicolon -- theory_keyword |-- args)) ||
 | 
|  |     77 |   theory_keyword |-- P.!!! args;
 | 
|  |     78 | 
 | 
|  |     79 | val old_header =
 | 
|  |     80 |   P.!!! (P.group "theory header"
 | 
|  |     81 |     (P.name -- (P.$$$ "=" |-- P.name -- Scan.repeat (P.$$$ "+" |-- P.name))))
 | 
|  |     82 |   >> (fn (A, (B, Bs)) => (A, B :: Bs, []: (string * bool) list));
 | 
|  |     83 | 
 | 
|  |     84 | fun scan src_pos =
 | 
|  |     85 |   (*sadly, old-style headers depend on the current (dynamic!) lexicon*)
 | 
|  |     86 |   if is_old src_pos then
 | 
|  |     87 |     scan_header ThySyn.get_lexicon (Scan.error old_header) src_pos
 | 
|  |     88 |   else scan_header (K header_lexicon) (Scan.error new_header) src_pos;
 | 
|  |     89 | 
 | 
|  |     90 | 
 | 
|  |     91 | end;
 |