src/Pure/Thy/thy_header.ML
changeset 46938 cda018294515
parent 46737 09ab89658a5d
child 46939 5b67ac48b384
equal deleted inserted replaced
46937:efb98d27dc1a 46938:cda018294515
     4 Theory headers -- independent of outer syntax.
     4 Theory headers -- independent of outer syntax.
     5 *)
     5 *)
     6 
     6 
     7 signature THY_HEADER =
     7 signature THY_HEADER =
     8 sig
     8 sig
     9   val args: Token.T list -> (string * string list * (string * bool) list) * Token.T list
     9   type header =
    10   val read: Position.T -> string -> string * string list * (Path.T * bool) list
    10    {name: string, imports: string list,
       
    11     keywords: (string * (string * string list) option) list,
       
    12     uses: (Path.T * bool) list}
       
    13   val make: string -> string list -> (string * (string * string list) option) list ->
       
    14     (Path.T * bool) list -> header
       
    15   val declare_keyword: string * (string * string list) option -> theory -> theory
       
    16   val the_keyword: theory -> string -> Keyword.T option
       
    17   val args: header parser
       
    18   val read: Position.T -> string -> header
    11 end;
    19 end;
    12 
    20 
    13 structure Thy_Header: THY_HEADER =
    21 structure Thy_Header: THY_HEADER =
    14 struct
    22 struct
    15 
    23 
    16 (* keywords *)
    24 type header =
       
    25  {name: string, imports: string list,
       
    26   keywords: (string * (string * string list) option) list,
       
    27   uses: (Path.T * bool) list};
       
    28 
       
    29 fun make name imports keywords uses : header =
       
    30   {name = name, imports = imports, keywords = keywords, uses = uses};
       
    31 
       
    32 
       
    33 
       
    34 (** keyword declarations **)
       
    35 
       
    36 fun err_dup name = error ("Inconsistent declaration of outer syntax keyword " ^ quote name);
       
    37 
       
    38 structure Data = Theory_Data
       
    39 (
       
    40   type T = Keyword.T option Symtab.table;
       
    41   val empty = Symtab.empty;
       
    42   val extend = I;
       
    43   fun merge data : T = Symtab.merge (op =) data handle Symtab.DUP name => err_dup name;
       
    44 );
       
    45 
       
    46 fun declare_keyword (name, kind) =
       
    47   Data.map (fn data =>
       
    48     Symtab.update_new (name, Option.map Keyword.make kind) data
       
    49       handle Symtab.DUP name => err_dup name);
       
    50 
       
    51 fun the_keyword thy name =
       
    52   (case Symtab.lookup (Data.get thy) name of
       
    53     SOME decl => decl
       
    54   | NONE => error ("Unknown outer syntax keyword " ^ quote name));
       
    55 
       
    56 
       
    57 
       
    58 (** concrete syntax **)
       
    59 
       
    60 (* header keywords *)
    17 
    61 
    18 val headerN = "header";
    62 val headerN = "header";
    19 val theoryN = "theory";
    63 val theoryN = "theory";
    20 val importsN = "imports";
    64 val importsN = "imports";
       
    65 val keywordsN = "keywords";
    21 val usesN = "uses";
    66 val usesN = "uses";
    22 val beginN = "begin";
    67 val beginN = "begin";
    23 
    68 
    24 val header_lexicon = Scan.make_lexicon
    69 val header_lexicon =
    25   (map Symbol.explode ["%", "(", ")", ";", beginN, headerN, importsN, theoryN, usesN]);
    70   Scan.make_lexicon
       
    71     (map Symbol.explode
       
    72       ["%", "(", ")", "::", ";", "and", beginN, headerN, importsN, keywordsN, theoryN, usesN]);
    26 
    73 
    27 
    74 
    28 (* header args *)
    75 (* header args *)
    29 
    76 
    30 val file_name = Parse.group (fn () => "file name") Parse.name;
    77 local
       
    78 
       
    79 val file_name = Parse.group (fn () => "file name") Parse.path;
    31 val theory_name = Parse.group (fn () => "theory name") Parse.name;
    80 val theory_name = Parse.group (fn () => "theory name") Parse.name;
       
    81 
       
    82 val keyword_kind = Parse.group (fn () => "outer syntax keyword kind") (Parse.name -- Parse.tags);
       
    83 val keyword_decl = Parse.name -- Scan.option (Parse.$$$ "::" |-- Parse.!!! keyword_kind);
    32 
    84 
    33 val file =
    85 val file =
    34   Parse.$$$ "(" |-- Parse.!!! (file_name --| Parse.$$$ ")") >> rpair false ||
    86   Parse.$$$ "(" |-- Parse.!!! (file_name --| Parse.$$$ ")") >> rpair false ||
    35   file_name >> rpair true;
    87   file_name >> rpair true;
    36 
    88 
    37 val uses = Scan.optional (Parse.$$$ usesN |-- Parse.!!! (Scan.repeat1 file)) [];
    89 in
    38 
    90 
    39 val args =
    91 val args =
    40   theory_name -- (Parse.$$$ importsN |--
    92   theory_name --
    41     Parse.!!! (Scan.repeat1 theory_name -- uses --| Parse.$$$ beginN))
    93   (Parse.$$$ importsN |-- Parse.!!! (Scan.repeat1 theory_name)) --
    42   >> Parse.triple2;
    94   Scan.optional (Parse.$$$ keywordsN |-- Parse.!!! (Parse.and_list1 keyword_decl)) [] --
       
    95   Scan.optional (Parse.$$$ usesN |-- Parse.!!! (Scan.repeat1 file)) [] --|
       
    96   Parse.$$$ beginN >>
       
    97   (fn (((name, imports), keywords), uses) => make name imports keywords uses);
       
    98 
       
    99 end;
    43 
   100 
    44 
   101 
    45 (* read header *)
   102 (* read header *)
    46 
   103 
    47 val header =
   104 val header =
    59     |> Token.source_proper
   116     |> Token.source_proper
    60     |> Source.source Token.stopper (Scan.single (Scan.error (Parse.!!! header))) NONE
   117     |> Source.source Token.stopper (Scan.single (Scan.error (Parse.!!! header))) NONE
    61     |> Source.get_single;
   118     |> Source.get_single;
    62   in
   119   in
    63     (case res of
   120     (case res of
    64       SOME ((name, imports, uses), _) => (name, imports, map (apfst Path.explode) uses)
   121       SOME (h, _) => h
    65     | NONE => error ("Unexpected end of input" ^ Position.str_of pos))
   122     | NONE => error ("Unexpected end of input" ^ Position.str_of pos))
    66   end;
   123   end;
    67 
   124 
    68 end;
   125 end;