src/Pure/Isar/outer_syntax.ML
changeset 58999 ed09ae4ea2d8
parent 58934 385a4cc7426f
child 59083 88b0b1f28adc
equal deleted inserted replaced
58998:6237574c705b 58999:ed09ae4ea2d8
     4 Isabelle/Isar outer syntax.
     4 Isabelle/Isar outer syntax.
     5 *)
     5 *)
     6 
     6 
     7 signature OUTER_SYNTAX =
     7 signature OUTER_SYNTAX =
     8 sig
     8 sig
     9   datatype markup = Markup | Markup_Env | Verbatim
       
    10   val is_markup: theory -> markup -> string -> bool
       
    11   val help: theory -> string list -> unit
     9   val help: theory -> string list -> unit
    12   val print_commands: theory -> unit
    10   val print_commands: theory -> unit
    13   type command_spec = string * Position.T
    11   type command_spec = string * Position.T
    14   val command: command_spec -> string ->
    12   val command: command_spec -> string ->
    15     (Toplevel.transition -> Toplevel.transition) parser -> unit
       
    16   val markup_command: markup -> command_spec -> string ->
       
    17     (Toplevel.transition -> Toplevel.transition) parser -> unit
    13     (Toplevel.transition -> Toplevel.transition) parser -> unit
    18   val local_theory': command_spec -> string ->
    14   val local_theory': command_spec -> string ->
    19     (bool -> local_theory -> local_theory) parser -> unit
    15     (bool -> local_theory -> local_theory) parser -> unit
    20   val local_theory: command_spec -> string ->
    16   val local_theory: command_spec -> string ->
    21     (local_theory -> local_theory) parser -> unit
    17     (local_theory -> local_theory) parser -> unit
    45   err_command "Duplicate outer syntax command " name ps;
    41   err_command "Duplicate outer syntax command " name ps;
    46 
    42 
    47 
    43 
    48 (* command parsers *)
    44 (* command parsers *)
    49 
    45 
    50 datatype markup = Markup | Markup_Env | Verbatim;
       
    51 
       
    52 datatype command = Command of
    46 datatype command = Command of
    53  {comment: string,
    47  {comment: string,
    54   markup: markup option,
       
    55   parse: (Toplevel.transition -> Toplevel.transition) parser,
    48   parse: (Toplevel.transition -> Toplevel.transition) parser,
    56   pos: Position.T,
    49   pos: Position.T,
    57   id: serial};
    50   id: serial};
    58 
    51 
    59 fun eq_command (Command {id = id1, ...}, Command {id = id2, ...}) = id1 = id2;
    52 fun eq_command (Command {id = id1, ...}, Command {id = id2, ...}) = id1 = id2;
    60 
    53 
    61 fun new_command comment markup parse pos =
    54 fun new_command comment parse pos =
    62   Command {comment = comment, markup = markup, parse = parse, pos = pos, id = serial ()};
    55   Command {comment = comment, parse = parse, pos = pos, id = serial ()};
    63 
    56 
    64 fun command_pos (Command {pos, ...}) = pos;
    57 fun command_pos (Command {pos, ...}) = pos;
    65 
    58 
    66 fun command_markup def (name, Command {pos, id, ...}) =
    59 fun command_markup def (name, Command {pos, id, ...}) =
    67   Markup.properties (Position.entity_properties_of def id pos)
    60   Markup.properties (Position.entity_properties_of def id pos)
    72     (Pretty.marks_str
    65     (Pretty.marks_str
    73       ([Active.make_markup Markup.sendbackN {implicit = true, properties = [Markup.padding_line]},
    66       ([Active.make_markup Markup.sendbackN {implicit = true, properties = [Markup.padding_line]},
    74         command_markup false cmd], name) :: Pretty.str ":" :: Pretty.brk 2 :: Pretty.text comment);
    67         command_markup false cmd], name) :: Pretty.str ":" :: Pretty.brk 2 :: Pretty.text comment);
    75 
    68 
    76 
    69 
    77 (* type syntax *)
    70 (* theory data *)
    78 
       
    79 datatype syntax = Syntax of
       
    80  {commands: command Symtab.table,
       
    81   markups: (string * markup) list};
       
    82 
       
    83 fun make_syntax (commands, markups) =
       
    84   Syntax {commands = commands, markups = markups};
       
    85 
    71 
    86 structure Data = Theory_Data
    72 structure Data = Theory_Data
    87 (
    73 (
    88   type T = syntax;
    74   type T = command Symtab.table;
    89   val empty = make_syntax (Symtab.empty, []);
    75   val empty = Symtab.empty;
    90   val extend = I;
    76   val extend = I;
    91   fun merge (Syntax {commands = commands1, markups = markups1},
    77   fun merge data : T =
    92       Syntax {commands = commands2, markups = markups2}) =
    78     data |> Symtab.join (fn name => fn (cmd1, cmd2) =>
    93     let
    79       if eq_command (cmd1, cmd2) then raise Symtab.SAME
    94       val commands' = (commands1, commands2)
    80       else err_dup_command name [command_pos cmd1, command_pos cmd2]);
    95         |> Symtab.join (fn name => fn (cmd1, cmd2) =>
       
    96           if eq_command (cmd1, cmd2) then raise Symtab.SAME
       
    97           else err_dup_command name [command_pos cmd1, command_pos cmd2]);
       
    98       val markups' = AList.merge (op =) (K true) (markups1, markups2);
       
    99     in make_syntax (commands', markups') end;
       
   100 );
    81 );
   101 
    82 
   102 
    83 val get_commands = Data.get;
   103 (* inspect syntax *)
    84 val dest_commands = get_commands #> Symtab.dest #> sort_wrt #1;
   104 
    85 val lookup_commands = Symtab.lookup o get_commands;
   105 val get_syntax = Data.get;
       
   106 
       
   107 val dest_commands =
       
   108   get_syntax #> (fn Syntax {commands, ...} => commands |> Symtab.dest |> sort_wrt #1);
       
   109 
       
   110 val lookup_commands =
       
   111   get_syntax #> (fn Syntax {commands, ...} => Symtab.lookup commands);
       
   112 
       
   113 val is_markup =
       
   114   get_syntax #> (fn Syntax {markups, ...} => fn kind => fn name =>
       
   115     AList.lookup (op =) markups name = SOME kind);
       
   116 
    86 
   117 fun help thy pats =
    87 fun help thy pats =
   118   dest_commands thy
    88   dest_commands thy
   119   |> filter (fn (name, _) => forall (fn pat => match_string pat name) pats)
    89   |> filter (fn (name, _) => forall (fn pat => match_string pat name) pats)
   120   |> map pretty_command
    90   |> map pretty_command
   130       Pretty.big_list "commands:" (map pretty_command commands)]
   100       Pretty.big_list "commands:" (map pretty_command commands)]
   131     |> Pretty.writeln_chunks
   101     |> Pretty.writeln_chunks
   132   end;
   102   end;
   133 
   103 
   134 
   104 
   135 (* build syntax *)
   105 (* maintain commands *)
   136 
   106 
   137 fun add_command name cmd thy = thy |> Data.map (fn Syntax {commands, ...} =>
   107 fun add_command name cmd thy =
   138   let
   108   let
   139     val keywords = Thy_Header.get_keywords thy;
   109     val _ =
   140     val _ =
   110       Keyword.is_command (Thy_Header.get_keywords thy) name orelse
   141       Keyword.is_command keywords name orelse
       
   142         err_command "Undeclared outer syntax command " name [command_pos cmd];
   111         err_command "Undeclared outer syntax command " name [command_pos cmd];
   143 
   112     val _ =
   144     val _ =
   113       (case lookup_commands thy name of
   145       (case Symtab.lookup commands name of
       
   146         NONE => ()
   114         NONE => ()
   147       | SOME cmd' => err_dup_command name [command_pos cmd, command_pos cmd']);
   115       | SOME cmd' => err_dup_command name [command_pos cmd, command_pos cmd']);
   148 
       
   149     val _ =
   116     val _ =
   150       Context_Position.report_generic (ML_Context.the_generic_context ())
   117       Context_Position.report_generic (ML_Context.the_generic_context ())
   151         (command_pos cmd) (command_markup true (name, cmd));
   118         (command_pos cmd) (command_markup true (name, cmd));
   152 
   119   in Data.map (Symtab.update (name, cmd)) thy end;
   153     val commands' = Symtab.update (name, cmd) commands;
       
   154     val markups' =
       
   155       Symtab.fold (fn (name, Command {markup = SOME m, ...}) => cons (name, m) | _ => I)
       
   156         commands' [];
       
   157   in make_syntax (commands', markups') end);
       
   158 
   120 
   159 val _ = Theory.setup (Theory.at_end (fn thy =>
   121 val _ = Theory.setup (Theory.at_end (fn thy =>
   160   let
   122   let
   161     val keywords = Thy_Header.get_keywords thy;
   123     val command_keywords =
   162     val major = Keyword.major_keywords keywords;
   124       Scan.dest_lexicon (Keyword.major_keywords (Thy_Header.get_keywords thy));
   163     val _ =
   125     val _ =
   164       (case subtract (op =) (map #1 (dest_commands thy)) (Scan.dest_lexicon major) of
   126       (case subtract (op =) (map #1 (dest_commands thy)) command_keywords of
   165         [] => ()
   127         [] => ()
   166       | missing => error ("Missing outer syntax command(s) " ^ commas_quote missing))
   128       | missing => error ("Missing outer syntax command(s) " ^ commas_quote missing))
   167   in NONE end));
   129   in NONE end));
   168 
   130 
   169 
   131 
   170 (* implicit theory setup *)
   132 (* implicit theory setup *)
   171 
   133 
   172 type command_spec = string * Position.T;
   134 type command_spec = string * Position.T;
   173 
   135 
   174 fun command (name, pos) comment parse =
   136 fun command (name, pos) comment parse =
   175   Theory.setup (add_command name (new_command comment NONE parse pos));
   137   Theory.setup (add_command name (new_command comment parse pos));
   176 
       
   177 fun markup_command markup (name, pos) comment parse =
       
   178   Theory.setup (add_command name (new_command comment (SOME markup) parse pos));
       
   179 
   138 
   180 fun local_theory_command trans command_spec comment parse =
   139 fun local_theory_command trans command_spec comment parse =
   181   command command_spec comment (Parse.opt_target -- parse >> (fn (loc, f) => trans loc f));
   140   command command_spec comment (Parse.opt_target -- parse >> (fn (loc, f) => trans loc f));
   182 
   141 
   183 val local_theory' = local_theory_command Toplevel.local_theory';
   142 val local_theory' = local_theory_command Toplevel.local_theory';