src/Pure/Isar/keyword.ML
author wenzelm
Sun Jul 10 11:18:35 2016 +0200 (2016-07-10)
changeset 63429 baedd4724f08
parent 61618 27af754f50ca
child 63430 9c5fcd355a2d
permissions -rw-r--r--
tuned signature: more uniform Keyword.spec;
wenzelm@36949
     1
(*  Title:      Pure/Isar/keyword.ML
wenzelm@17059
     2
    Author:     Makarius
wenzelm@17059
     3
wenzelm@58900
     4
Isar keyword classification.
wenzelm@17059
     5
*)
wenzelm@17059
     6
wenzelm@36949
     7
signature KEYWORD =
wenzelm@17059
     8
sig
wenzelm@58928
     9
  val diag: string
wenzelm@58999
    10
  val document_heading: string
wenzelm@58999
    11
  val document_body: string
wenzelm@58999
    12
  val document_raw: string
wenzelm@58928
    13
  val thy_begin: string
wenzelm@58928
    14
  val thy_end: string
wenzelm@58928
    15
  val thy_decl: string
wenzelm@58928
    16
  val thy_decl_block: string
wenzelm@58928
    17
  val thy_load: string
wenzelm@58928
    18
  val thy_goal: string
wenzelm@58928
    19
  val qed: string
wenzelm@58928
    20
  val qed_script: string
wenzelm@58928
    21
  val qed_block: string
wenzelm@58928
    22
  val qed_global: string
wenzelm@58928
    23
  val prf_goal: string
wenzelm@58928
    24
  val prf_block: string
wenzelm@60694
    25
  val next_block: string
wenzelm@58928
    26
  val prf_open: string
wenzelm@58928
    27
  val prf_close: string
wenzelm@58928
    28
  val prf_chain: string
wenzelm@58928
    29
  val prf_decl: string
wenzelm@58928
    30
  val prf_asm: string
wenzelm@58928
    31
  val prf_asm_goal: string
wenzelm@58928
    32
  val prf_script: string
wenzelm@60624
    33
  val prf_script_goal: string
wenzelm@60624
    34
  val prf_script_asm_goal: string
wenzelm@48864
    35
  type spec = (string * string list) * string list
wenzelm@63429
    36
  val no_spec: spec
wenzelm@58903
    37
  type keywords
wenzelm@58903
    38
  val minor_keywords: keywords -> Scan.lexicon
wenzelm@58903
    39
  val major_keywords: keywords -> Scan.lexicon
wenzelm@58920
    40
  val no_command_keywords: keywords -> keywords
wenzelm@58903
    41
  val empty_keywords: keywords
wenzelm@58903
    42
  val merge_keywords: keywords * keywords -> keywords
wenzelm@63429
    43
  val add_keywords: ((string * Position.T) * spec) list -> keywords -> keywords
wenzelm@58931
    44
  val is_keyword: keywords -> string -> bool
wenzelm@58931
    45
  val is_command: keywords -> string -> bool
wenzelm@58928
    46
  val is_literal: keywords -> string -> bool
wenzelm@61618
    47
  val dest_commands: keywords -> string list
wenzelm@59934
    48
  val command_markup: keywords -> string -> Markup.T option
wenzelm@59123
    49
  val command_kind: keywords -> string -> string option
wenzelm@58923
    50
  val command_files: keywords -> string -> Path.T -> Path.T list
wenzelm@58923
    51
  val command_tags: keywords -> string -> string list
wenzelm@58999
    52
  val is_vacuous: keywords -> string -> bool
wenzelm@58923
    53
  val is_diag: keywords -> string -> bool
wenzelm@58999
    54
  val is_document_heading: keywords -> string -> bool
wenzelm@58999
    55
  val is_document_body: keywords -> string -> bool
wenzelm@58999
    56
  val is_document_raw: keywords -> string -> bool
wenzelm@59033
    57
  val is_document: keywords -> string -> bool
wenzelm@59125
    58
  val is_theory_end: keywords -> string -> bool
wenzelm@58923
    59
  val is_theory_load: keywords -> string -> bool
wenzelm@58923
    60
  val is_theory: keywords -> string -> bool
wenzelm@58923
    61
  val is_theory_body: keywords -> string -> bool
wenzelm@58923
    62
  val is_proof: keywords -> string -> bool
wenzelm@58923
    63
  val is_proof_body: keywords -> string -> bool
wenzelm@58923
    64
  val is_theory_goal: keywords -> string -> bool
wenzelm@58923
    65
  val is_proof_goal: keywords -> string -> bool
wenzelm@58923
    66
  val is_qed: keywords -> string -> bool
wenzelm@58923
    67
  val is_qed_global: keywords -> string -> bool
wenzelm@60693
    68
  val is_proof_open: keywords -> string -> bool
wenzelm@60693
    69
  val is_proof_close: keywords -> string -> bool
wenzelm@59125
    70
  val is_proof_asm: keywords -> string -> bool
wenzelm@59125
    71
  val is_improper: keywords -> string -> bool
wenzelm@58923
    72
  val is_printed: keywords -> string -> bool
wenzelm@17059
    73
end;
wenzelm@17059
    74
wenzelm@36949
    75
structure Keyword: KEYWORD =
wenzelm@17059
    76
struct
wenzelm@17059
    77
wenzelm@27357
    78
(** keyword classification **)
wenzelm@17059
    79
wenzelm@58918
    80
(* kinds *)
wenzelm@58918
    81
wenzelm@58928
    82
val diag = "diag";
wenzelm@58999
    83
val document_heading = "document_heading";
wenzelm@58999
    84
val document_body = "document_body";
wenzelm@58999
    85
val document_raw = "document_raw";
wenzelm@58928
    86
val thy_begin = "thy_begin";
wenzelm@58928
    87
val thy_end = "thy_end";
wenzelm@58928
    88
val thy_decl = "thy_decl";
wenzelm@58928
    89
val thy_decl_block = "thy_decl_block";
wenzelm@58928
    90
val thy_load = "thy_load";
wenzelm@58928
    91
val thy_goal = "thy_goal";
wenzelm@58928
    92
val qed = "qed";
wenzelm@58928
    93
val qed_script = "qed_script";
wenzelm@58928
    94
val qed_block = "qed_block";
wenzelm@58928
    95
val qed_global = "qed_global";
wenzelm@58928
    96
val prf_goal = "prf_goal";
wenzelm@58928
    97
val prf_block = "prf_block";
wenzelm@60694
    98
val next_block = "next_block";
wenzelm@58928
    99
val prf_open = "prf_open";
wenzelm@58928
   100
val prf_close = "prf_close";
wenzelm@58928
   101
val prf_chain = "prf_chain";
wenzelm@58928
   102
val prf_decl = "prf_decl";
wenzelm@58928
   103
val prf_asm = "prf_asm";
wenzelm@58928
   104
val prf_asm_goal = "prf_asm_goal";
wenzelm@58928
   105
val prf_script = "prf_script";
wenzelm@60624
   106
val prf_script_goal = "prf_script_goal";
wenzelm@60624
   107
val prf_script_asm_goal = "prf_script_asm_goal";
wenzelm@58928
   108
wenzelm@58928
   109
val kinds =
wenzelm@58999
   110
  [diag, document_heading, document_body, document_raw, thy_begin, thy_end, thy_load, thy_decl,
wenzelm@60694
   111
    thy_decl_block, thy_goal, qed, qed_script, qed_block, qed_global, prf_goal, prf_block,
wenzelm@60694
   112
    next_block, prf_open, prf_close, prf_chain, prf_decl, prf_asm, prf_asm_goal, prf_script,
wenzelm@60694
   113
    prf_script_goal, prf_script_asm_goal];
wenzelm@58928
   114
wenzelm@58928
   115
wenzelm@58928
   116
(* specifications *)
wenzelm@58928
   117
wenzelm@59934
   118
type spec = (string * string list) * string list;
wenzelm@59934
   119
wenzelm@63429
   120
val no_spec: spec = (("", []), []);
wenzelm@63429
   121
wenzelm@59934
   122
type entry =
wenzelm@59934
   123
 {pos: Position.T,
wenzelm@59934
   124
  id: serial,
wenzelm@59934
   125
  kind: string,
wenzelm@48864
   126
  files: string list,  (*extensions of embedded files*)
wenzelm@58918
   127
  tags: string list};
wenzelm@17059
   128
wenzelm@59934
   129
fun check_spec pos ((kind, files), tags) : entry =
wenzelm@58918
   130
  if not (member (op =) kinds kind) then
wenzelm@58918
   131
    error ("Unknown outer syntax keyword kind " ^ quote kind)
wenzelm@58928
   132
  else if not (null files) andalso kind <> thy_load then
wenzelm@58918
   133
    error ("Illegal specification of files for " ^ quote kind)
wenzelm@59934
   134
  else {pos = pos, id = serial (), kind = kind, files = files, tags = tags};
wenzelm@46961
   135
wenzelm@46938
   136
wenzelm@58903
   137
(** keyword tables **)
wenzelm@58903
   138
wenzelm@58903
   139
(* type keywords *)
wenzelm@27357
   140
wenzelm@48874
   141
datatype keywords = Keywords of
wenzelm@58903
   142
 {minor: Scan.lexicon,
wenzelm@58903
   143
  major: Scan.lexicon,
wenzelm@59934
   144
  commands: entry Symtab.table};
wenzelm@58903
   145
wenzelm@58903
   146
fun minor_keywords (Keywords {minor, ...}) = minor;
wenzelm@58903
   147
fun major_keywords (Keywords {major, ...}) = major;
wenzelm@58903
   148
wenzelm@58906
   149
fun make_keywords (minor, major, commands) =
wenzelm@58906
   150
  Keywords {minor = minor, major = major, commands = commands};
wenzelm@46957
   151
wenzelm@58906
   152
fun map_keywords f (Keywords {minor, major, commands}) =
wenzelm@58906
   153
  make_keywords (f (minor, major, commands));
wenzelm@58903
   154
wenzelm@58920
   155
val no_command_keywords =
wenzelm@58920
   156
  map_keywords (fn (minor, _, _) => (minor, Scan.empty_lexicon, Symtab.empty));
wenzelm@58920
   157
wenzelm@58920
   158
wenzelm@58920
   159
(* build keywords *)
wenzelm@58920
   160
wenzelm@58903
   161
val empty_keywords =
wenzelm@58903
   162
  make_keywords (Scan.empty_lexicon, Scan.empty_lexicon, Symtab.empty);
wenzelm@48874
   163
wenzelm@58903
   164
fun merge_keywords
wenzelm@58906
   165
  (Keywords {minor = minor1, major = major1, commands = commands1},
wenzelm@58906
   166
    Keywords {minor = minor2, major = major2, commands = commands2}) =
wenzelm@58903
   167
  make_keywords
wenzelm@58903
   168
   (Scan.merge_lexicons (minor1, minor2),
wenzelm@58903
   169
    Scan.merge_lexicons (major1, major2),
wenzelm@58906
   170
    Symtab.merge (K true) (commands1, commands2));
wenzelm@27357
   171
wenzelm@58928
   172
val add_keywords =
wenzelm@63429
   173
  fold (fn ((name, pos), spec as ((kind, _), _)) => map_keywords (fn (minor, major, commands) =>
wenzelm@63429
   174
    if kind = "" then
wenzelm@63429
   175
      let
wenzelm@63429
   176
        val minor' = Scan.extend_lexicon (Symbol.explode name) minor;
wenzelm@63429
   177
      in (minor', major, commands) end
wenzelm@63429
   178
    else
wenzelm@63429
   179
      let
wenzelm@63429
   180
        val entry = check_spec pos spec;
wenzelm@63429
   181
        val major' = Scan.extend_lexicon (Symbol.explode name) major;
wenzelm@63429
   182
        val commands' = Symtab.update (name, entry) commands;
wenzelm@63429
   183
      in (minor, major', commands') end));
wenzelm@27357
   184
wenzelm@58903
   185
wenzelm@58931
   186
(* keyword status *)
wenzelm@27357
   187
wenzelm@58931
   188
fun is_keyword keywords s = Scan.is_literal (minor_keywords keywords) (Symbol.explode s);
wenzelm@58931
   189
fun is_command (Keywords {commands, ...}) = Symtab.defined commands;
wenzelm@58931
   190
fun is_literal keywords = is_keyword keywords orf is_command keywords;
wenzelm@27357
   191
wenzelm@61618
   192
fun dest_commands (Keywords {commands, ...}) = Symtab.keys commands;
wenzelm@61618
   193
wenzelm@58928
   194
wenzelm@59934
   195
(* command keywords *)
wenzelm@58931
   196
wenzelm@59123
   197
fun lookup_command (Keywords {commands, ...}) = Symtab.lookup commands;
wenzelm@59123
   198
wenzelm@59934
   199
fun command_markup keywords name =
wenzelm@59934
   200
  lookup_command keywords name
wenzelm@59934
   201
  |> Option.map (fn {pos, id, ...} =>
wenzelm@59934
   202
      Markup.properties (Position.entity_properties_of false id pos)
wenzelm@59935
   203
        (Markup.entity Markup.command_keywordN name));
wenzelm@59934
   204
wenzelm@59123
   205
fun command_kind keywords = Option.map #kind o lookup_command keywords;
wenzelm@54523
   206
wenzelm@58923
   207
fun command_files keywords name path =
wenzelm@59123
   208
  (case lookup_command keywords name of
wenzelm@54523
   209
    NONE => []
wenzelm@58928
   210
  | SOME {kind, files, ...} =>
wenzelm@58928
   211
      if kind <> thy_load then []
wenzelm@54523
   212
      else if null files then [path]
wenzelm@54523
   213
      else map (fn ext => Path.ext ext path) files);
wenzelm@54523
   214
wenzelm@58923
   215
fun command_tags keywords name =
wenzelm@59123
   216
  (case lookup_command keywords name of
wenzelm@58928
   217
    SOME {tags, ...} => tags
wenzelm@58918
   218
  | NONE => []);
wenzelm@27357
   219
wenzelm@27433
   220
wenzelm@28431
   221
(* command categories *)
wenzelm@27433
   222
wenzelm@51225
   223
fun command_category ks =
wenzelm@58923
   224
  let
wenzelm@58928
   225
    val tab = Symtab.make_set ks;
wenzelm@58923
   226
    fun pred keywords name =
wenzelm@59123
   227
      (case lookup_command keywords name of
wenzelm@51225
   228
        NONE => false
wenzelm@58928
   229
      | SOME {kind, ...} => Symtab.defined tab kind);
wenzelm@58923
   230
  in pred end;
wenzelm@27440
   231
wenzelm@58999
   232
val is_vacuous = command_category [diag, document_heading, document_body, document_raw];
wenzelm@58999
   233
wenzelm@29347
   234
val is_diag = command_category [diag];
wenzelm@40397
   235
wenzelm@58999
   236
val is_document_heading = command_category [document_heading];
wenzelm@58999
   237
val is_document_body = command_category [document_body];
wenzelm@58999
   238
val is_document_raw = command_category [document_raw];
wenzelm@58999
   239
val is_document = command_category [document_heading, document_body, document_raw];
wenzelm@29347
   240
wenzelm@59125
   241
val is_theory_end = command_category [thy_end];
wenzelm@29347
   242
wenzelm@48867
   243
val is_theory_load = command_category [thy_load];
wenzelm@48867
   244
wenzelm@27440
   245
val is_theory = command_category
wenzelm@58868
   246
  [thy_begin, thy_end, thy_load, thy_decl, thy_decl_block, thy_goal];
wenzelm@27440
   247
wenzelm@56944
   248
val is_theory_body = command_category
wenzelm@58868
   249
  [thy_load, thy_decl, thy_decl_block, thy_goal];
wenzelm@56944
   250
wenzelm@27440
   251
val is_proof = command_category
wenzelm@60694
   252
  [qed, qed_script, qed_block, qed_global, prf_goal, prf_block, next_block, prf_open,
wenzelm@60694
   253
    prf_close, prf_chain, prf_decl, prf_asm, prf_asm_goal, prf_script, prf_script_goal,
wenzelm@60624
   254
    prf_script_asm_goal];
wenzelm@28431
   255
wenzelm@51225
   256
val is_proof_body = command_category
wenzelm@60694
   257
  [diag, document_heading, document_body, document_raw, prf_block, next_block, prf_open,
wenzelm@60694
   258
    prf_close, prf_chain, prf_decl, prf_asm, prf_asm_goal, prf_script, prf_script_goal,
wenzelm@60624
   259
    prf_script_asm_goal];
wenzelm@51225
   260
wenzelm@51274
   261
val is_theory_goal = command_category [thy_goal];
wenzelm@60624
   262
val is_proof_goal = command_category [prf_goal, prf_asm_goal, prf_script_goal, prf_script_asm_goal];
wenzelm@53571
   263
val is_qed = command_category [qed, qed_script, qed_block];
wenzelm@28431
   264
val is_qed_global = command_category [qed_global];
wenzelm@27520
   265
wenzelm@60693
   266
val is_proof_open =
wenzelm@60693
   267
  command_category [prf_goal, prf_asm_goal, prf_script_goal, prf_script_asm_goal, prf_open];
wenzelm@60693
   268
val is_proof_close = command_category [qed, qed_script, qed_block, prf_close];
wenzelm@60693
   269
wenzelm@59125
   270
val is_proof_asm = command_category [prf_asm, prf_asm_goal];
wenzelm@60624
   271
val is_improper = command_category [qed_script, prf_script, prf_script_goal, prf_script_asm_goal];
wenzelm@59125
   272
wenzelm@58923
   273
fun is_printed keywords = is_theory_goal keywords orf is_proof keywords;
wenzelm@58923
   274
wenzelm@27357
   275
end;