src/Pure/Isar/keyword.ML
author Walther Neuper <walther.neuper@jku.at>
Mon, 08 Mar 2021 08:17:28 +0100
changeset 60163 002e3ecd3108
parent 60156 82777b2afa44
child 60166 7d6f46b7fc10
permissions -rw-r--r--
step 6.10: stop unsuccessful trials with combination of types on Outer_Syntax

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