src/HOL/SPARK/Tools/fdl_parser.ML
author Walther Neuper <walther.neuper@jku.at>
Fri, 12 Mar 2021 12:48:55 +0100
changeset 60171 f7060b6860cd
parent 60166 7d6f46b7fc10
child 60200 dba15a58a36a
permissions -rw-r--r--
Isabelle2020->21: adapt SPARK to ParseC
berghofe@41809
     1
(*  Title:      HOL/SPARK/Tools/fdl_parser.ML
berghofe@41809
     2
    Author:     Stefan Berghofer
berghofe@41809
     3
    Copyright:  secunet Security Networks AG
berghofe@41809
     4
berghofe@41809
     5
Parser for fdl files.
berghofe@41809
     6
*)
berghofe@41809
     7
berghofe@41809
     8
signature FDL_PARSER =
berghofe@41809
     9
sig
berghofe@41809
    10
  datatype expr =
berghofe@41809
    11
      Ident of string
berghofe@41809
    12
    | Number of int
berghofe@41809
    13
    | Quantifier of string * string list * string * expr
berghofe@41809
    14
    | Funct of string * expr list
berghofe@41809
    15
    | Element of expr * expr list
berghofe@41809
    16
    | Update of expr * expr list * expr
berghofe@41809
    17
    | Record of string * (string * expr) list
berghofe@41809
    18
    | Array of string * expr option *
berghofe@41809
    19
        ((expr * expr option) list list * expr) list;
berghofe@41809
    20
berghofe@41809
    21
  datatype fdl_type =
berghofe@41809
    22
      Basic_Type of string
berghofe@41809
    23
    | Enum_Type of string list
berghofe@41809
    24
    | Array_Type of string list * string
berghofe@41809
    25
    | Record_Type of (string list * string) list
berghofe@41809
    26
    | Pending_Type;
berghofe@41809
    27
berghofe@41809
    28
  datatype fdl_rule =
berghofe@41809
    29
      Inference_Rule of expr list * expr
berghofe@41809
    30
    | Substitution_Rule of expr list * expr * expr;
berghofe@41809
    31
berghofe@41809
    32
  type rules =
berghofe@41809
    33
    ((string * int) * fdl_rule) list *
berghofe@41809
    34
    (string * (expr * (string * string) list) list) list;
walther@60171
    35
  val empty_rules: rules
berghofe@41809
    36
berghofe@41809
    37
  type vcs = (string * (string *
berghofe@41809
    38
    ((string * expr) list * (string * expr) list)) list) list;
walther@60171
    39
  val empty_vcs: (string * string) * vcs
berghofe@41809
    40
berghofe@41809
    41
  type 'a tab = 'a Symtab.table * (string * 'a) list;
berghofe@41809
    42
berghofe@41809
    43
  val lookup: 'a tab -> string -> 'a option;
berghofe@41809
    44
  val update: string * 'a -> 'a tab -> 'a tab;
berghofe@41809
    45
  val items: 'a tab -> (string * 'a) list;
berghofe@41809
    46
berghofe@41809
    47
  type decls =
berghofe@41809
    48
    {types: fdl_type tab,
berghofe@41809
    49
     vars: string tab,
berghofe@41809
    50
     consts: string tab,
berghofe@41809
    51
     funs: (string list * string) tab};
walther@60171
    52
  val empty_decls: decls
berghofe@41809
    53
berghofe@41809
    54
  val parse_vcs: (Fdl_Lexer.chars -> 'a * Fdl_Lexer.chars) -> Position.T ->
berghofe@41809
    55
    string -> 'a * ((string * string) * vcs);
berghofe@41809
    56
berghofe@41809
    57
  val parse_declarations:  Position.T -> string -> (string * string) * decls;
berghofe@41809
    58
berghofe@41809
    59
  val parse_rules: Position.T -> string -> rules;
walther@60171
    60
  val vcs: Fdl_Lexer.T list ->
walther@60171
    61
    ((string * string) * (string * (string * ((string * expr) list * (string * expr) list)) list) list) * Fdl_Lexer.T list;
walther@60171
    62
  val !!! : (Fdl_Lexer.T list -> 'a) -> Fdl_Lexer.T list -> 'a;
walther@60171
    63
  val $$$ : string -> Fdl_Lexer.T list -> string * Fdl_Lexer.T list
walther@60171
    64
  val group: string -> ('a -> 'b) -> 'a -> 'b
walther@60171
    65
  val identifier: Fdl_Lexer.T list -> string * Fdl_Lexer.T list
walther@60171
    66
  val enum1: string -> (Fdl_Lexer.T list -> 'a * Fdl_Lexer.T list) -> Fdl_Lexer.T list ->
walther@60171
    67
    'a list * Fdl_Lexer.T list
walther@60171
    68
  val list1: (Fdl_Lexer.T list -> 'a * Fdl_Lexer.T list) -> Fdl_Lexer.T list ->
walther@60171
    69
    'a list * Fdl_Lexer.T list
berghofe@41809
    70
end;
berghofe@41809
    71
walther@60171
    72
structure Fdl_Parser(**): FDL_PARSER(**) =
berghofe@41809
    73
struct
berghofe@41809
    74
berghofe@41809
    75
(** error handling **)
berghofe@41809
    76
berghofe@41809
    77
fun beginning n cs =
berghofe@41809
    78
  let val dots = if length cs > n then " ..." else "";
berghofe@41809
    79
  in
berghofe@41809
    80
    space_implode " " (take n cs) ^ dots
berghofe@41809
    81
  end;
berghofe@41809
    82
berghofe@41809
    83
fun !!! scan =
berghofe@41809
    84
  let
wenzelm@49926
    85
    fun get_pos [] = " (end-of-input)"
berghofe@41809
    86
      | get_pos (tok :: _) = Fdl_Lexer.pos_of tok;
berghofe@41809
    87
wenzelm@44818
    88
    fun err (syms, msg) = fn () =>
berghofe@41809
    89
      "Syntax error" ^ get_pos syms ^ " at " ^
wenzelm@44818
    90
        beginning 10 (map Fdl_Lexer.unparse syms) ^
wenzelm@44818
    91
        (case msg of NONE => "" | SOME m => "\n" ^ m () ^ " expected");
berghofe@41809
    92
  in Scan.!! err scan end;
berghofe@41809
    93
berghofe@41809
    94
fun parse_all p =
berghofe@41809
    95
  Scan.repeat (Scan.unless (Scan.one Fdl_Lexer.is_eof) (!!! p));
berghofe@41809
    96
berghofe@41809
    97
berghofe@41809
    98
(** parsers **)
berghofe@41809
    99
wenzelm@44818
   100
fun group s p = p || Scan.fail_with (K (fn () => s));
berghofe@41809
   101
berghofe@41809
   102
fun $$$ s = group s
berghofe@41809
   103
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Keyword andalso
berghofe@41809
   104
     Fdl_Lexer.content_of t = s) >> K s);
berghofe@41809
   105
berghofe@41809
   106
val identifier = group "identifier"
berghofe@41809
   107
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Ident) >>
berghofe@41809
   108
     Fdl_Lexer.content_of);
berghofe@41809
   109
berghofe@41809
   110
val long_identifier = group "long identifier"
berghofe@41809
   111
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Long_Ident) >>
berghofe@41809
   112
     Fdl_Lexer.content_of);
berghofe@41809
   113
berghofe@41809
   114
fun the_identifier s = group s
berghofe@41809
   115
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Ident andalso
berghofe@41809
   116
     Fdl_Lexer.content_of t = s) >> K s);
berghofe@41809
   117
berghofe@41809
   118
fun prfx_identifier g s = group g
berghofe@41809
   119
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Ident andalso
berghofe@41809
   120
     can (unprefix s) (Fdl_Lexer.content_of t)) >>
berghofe@41809
   121
     (unprefix s o Fdl_Lexer.content_of));
berghofe@41809
   122
berghofe@41809
   123
val mk_identifier = prfx_identifier "identifier \"mk__...\"" "mk__";
berghofe@41809
   124
val hyp_identifier = prfx_identifier "hypothesis identifer" "H";
berghofe@41809
   125
val concl_identifier = prfx_identifier "conclusion identifier" "C";
berghofe@41809
   126
berghofe@41809
   127
val number = group "number"
berghofe@41809
   128
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Number) >>
berghofe@41809
   129
     (the o Int.fromString o Fdl_Lexer.content_of));
berghofe@41809
   130
berghofe@41809
   131
val traceability = group "traceability information"
berghofe@41809
   132
  (Scan.one (fn t => Fdl_Lexer.kind_of t = Fdl_Lexer.Traceability) >>
berghofe@41809
   133
     Fdl_Lexer.content_of);
berghofe@41809
   134
berghofe@41809
   135
fun enum1 sep scan = scan ::: Scan.repeat ($$$ sep |-- !!! scan);
berghofe@41809
   136
fun enum sep scan = enum1 sep scan || Scan.succeed [];
berghofe@41809
   137
berghofe@41809
   138
fun list1 scan = enum1 "," scan;
berghofe@41809
   139
fun list scan = enum "," scan;
berghofe@41809
   140
berghofe@41809
   141
berghofe@41809
   142
(* expressions, see section 4.4 of SPARK Proof Manual *)
berghofe@41809
   143
berghofe@41809
   144
datatype expr =
berghofe@41809
   145
    Ident of string
berghofe@41809
   146
  | Number of int
berghofe@41809
   147
  | Quantifier of string * string list * string * expr
berghofe@41809
   148
  | Funct of string * expr list
berghofe@41809
   149
  | Element of expr * expr list
berghofe@41809
   150
  | Update of expr * expr list * expr
berghofe@41809
   151
  | Record of string * (string * expr) list
berghofe@41809
   152
  | Array of string * expr option *
berghofe@41809
   153
      ((expr * expr option) list list * expr) list;
berghofe@41809
   154
berghofe@41809
   155
fun unop (f, x) = Funct (f, [x]);
berghofe@41809
   156
berghofe@41809
   157
fun binop p q = p :|-- (fn x => Scan.optional
berghofe@41809
   158
  (q -- !!! p >> (fn (f, y) => Funct (f, [x, y]))) x);
berghofe@41809
   159
berghofe@41809
   160
(* left-associative *)
berghofe@41809
   161
fun binops opp argp =
berghofe@41809
   162
  argp -- Scan.repeat (opp -- !!! argp) >> (fn (x, fys) =>
berghofe@41809
   163
    fold (fn (f, y) => fn x => Funct (f, [x, y])) fys x);
berghofe@41809
   164
berghofe@41809
   165
(* right-associative *)
berghofe@41809
   166
fun binops' f p = enum1 f p >> foldr1 (fn (x, y) => Funct (f, [x, y]));
berghofe@41809
   167
berghofe@41809
   168
val multiplying_operator = $$$ "*" || $$$ "/" || $$$ "div" || $$$ "mod";
berghofe@41809
   169
berghofe@41809
   170
val adding_operator = $$$ "+" || $$$ "-";
berghofe@41809
   171
berghofe@41809
   172
val relational_operator =
berghofe@41809
   173
     $$$ "=" || $$$ "<>"
berghofe@41809
   174
  || $$$ "<" || $$$ ">"
berghofe@41809
   175
  || $$$ "<="|| $$$ ">=";
berghofe@41809
   176
berghofe@41809
   177
val quantification_kind = $$$ "for_all" || $$$ "for_some";
berghofe@41809
   178
berghofe@41809
   179
val quantification_generator =
berghofe@41809
   180
  list1 identifier --| $$$ ":" -- identifier;
berghofe@41809
   181
berghofe@51013
   182
fun opt_parens p = $$$ "(" |-- p --| $$$ ")" || p;
berghofe@51013
   183
berghofe@41809
   184
fun expression xs = group "expression"
berghofe@41809
   185
  (binop disjunction ($$$ "->" || $$$ "<->")) xs
berghofe@41809
   186
berghofe@41809
   187
and disjunction xs = binops' "or" conjunction xs
berghofe@41809
   188
berghofe@41809
   189
and conjunction xs = binops' "and" negation xs
berghofe@41809
   190
berghofe@41809
   191
and negation xs =
berghofe@41809
   192
  (   $$$ "not" -- !!! relation >> unop
berghofe@41809
   193
   || relation) xs
berghofe@41809
   194
berghofe@41809
   195
and relation xs = binop sum relational_operator xs
berghofe@41809
   196
berghofe@41809
   197
and sum xs = binops adding_operator term xs
berghofe@41809
   198
berghofe@41809
   199
and term xs = binops multiplying_operator factor xs
berghofe@41809
   200
berghofe@41809
   201
and factor xs =
berghofe@41809
   202
  (   $$$ "+" |-- !!! primary
berghofe@41809
   203
   || $$$ "-" -- !!! primary >> unop
berghofe@41809
   204
   || binop primary ($$$ "**")) xs
berghofe@41809
   205
berghofe@41809
   206
and primary xs = group "primary"
berghofe@41809
   207
  (   number >> Number
berghofe@41809
   208
   || $$$ "(" |-- !!! (expression --| $$$ ")")
berghofe@41809
   209
   || quantified_expression
berghofe@41809
   210
   || function_designator
berghofe@41809
   211
   || identifier >> Ident) xs
berghofe@41809
   212
berghofe@41809
   213
and quantified_expression xs = (quantification_kind --
berghofe@41809
   214
  !!! ($$$ "(" |-- quantification_generator --|  $$$ "," --
berghofe@41809
   215
    expression --| $$$ ")") >> (fn (q, ((xs, T), e)) =>
berghofe@41809
   216
      Quantifier (q, xs, T, e))) xs
berghofe@41809
   217
berghofe@41809
   218
and function_designator xs =
berghofe@41809
   219
  (   mk_identifier --| $$$ "(" :|--
berghofe@41809
   220
        (fn s => record_args s || array_args s) --| $$$ ")"
berghofe@41809
   221
   || $$$ "element" |-- !!! ($$$ "(" |-- expression --| $$$ "," --| $$$ "[" --
berghofe@41809
   222
        list1 expression --| $$$ "]" --| $$$ ")") >> Element
berghofe@41809
   223
   || $$$ "update" |-- !!! ($$$ "(" |-- expression --| $$$ "," --| $$$ "[" --
berghofe@41809
   224
        list1 expression --| $$$ "]" --| $$$ "," -- expression --| $$$ ")") >>
berghofe@41809
   225
          (fn ((A, xs), x) => Update (A, xs, x))
berghofe@41809
   226
   || identifier --| $$$ "(" -- !!! (list1 expression --| $$$ ")") >> Funct) xs
berghofe@41809
   227
berghofe@41809
   228
and record_args s xs =
berghofe@41809
   229
  (list1 (identifier --| $$$ ":=" -- !!! expression) >> (pair s #> Record)) xs
berghofe@41809
   230
berghofe@41809
   231
and array_args s xs =
berghofe@51013
   232
  (   array_associations >> (fn assocs => Array (s, NONE, assocs))
berghofe@51013
   233
   || expression -- Scan.optional ($$$ "," |-- !!! array_associations) [] >>
berghofe@51013
   234
        (fn (default, assocs) => Array (s, SOME default, assocs))) xs
berghofe@41809
   235
berghofe@41809
   236
and array_associations xs =
berghofe@51013
   237
  (list1 (opt_parens (enum1 "&" ($$$ "[" |--
berghofe@41809
   238
     !!! (list1 (expression -- Scan.option ($$$ ".." |-- !!! expression)) --|
berghofe@51013
   239
       $$$ "]"))) --| $$$ ":=" -- expression)) xs;
berghofe@41809
   240
berghofe@41809
   241
berghofe@41809
   242
(* verification conditions *)
berghofe@41809
   243
berghofe@41809
   244
type vcs = (string * (string *
berghofe@41809
   245
  ((string * expr) list * (string * expr) list)) list) list;
berghofe@41809
   246
berghofe@41809
   247
val vc =
berghofe@41809
   248
  identifier --| $$$ "." -- !!!
berghofe@41809
   249
    (   $$$ "***" |-- !!! (the_identifier "true" --| $$$ ".") >>
berghofe@41809
   250
          (Ident #> pair "1" #> single #> pair [])
berghofe@41809
   251
     || $$$ "!!!" |-- !!! (the_identifier "false" --| $$$ ".") >>
berghofe@41809
   252
          (Ident #> pair "1" #> single #> pair [])
berghofe@41809
   253
     || Scan.repeat1 (hyp_identifier --
berghofe@41809
   254
          !!! ($$$ ":" |-- expression --| $$$ ".")) --| $$$ "->" --
berghofe@41809
   255
        Scan.repeat1 (concl_identifier --
berghofe@41809
   256
          !!! ($$$ ":" |-- expression --| $$$ ".")));
berghofe@41809
   257
berghofe@41809
   258
val subprogram_kind = $$$ "function" || $$$ "procedure";
berghofe@41809
   259
berghofe@41809
   260
val vcs =
berghofe@41809
   261
  subprogram_kind -- (long_identifier || identifier) --
berghofe@41809
   262
  parse_all (traceability -- !!! (Scan.repeat1 vc));
walther@60171
   263
val empty_vcs = (("e_procedure", "e_G_C_D"), []: vcs)
berghofe@41809
   264
berghofe@41809
   265
fun parse_vcs header pos s =
walther@60171
   266
(*line_1*)s |>
walther@60171
   267
(*line_2*)Fdl_Lexer.tokenize header Fdl_Lexer.c_comment pos ||>
walther@60171
   268
(*line_3*)filter Fdl_Lexer.is_proper ||>
walther@60171
   269
(*line_4*)Scan.finite Fdl_Lexer.stopper (Scan.error (!!! vcs)) ||>
walther@60171
   270
(*line_5*)fst;
walther@60171
   271
(*            vvvvvv-------- = Fdl_Lexer.siv_header*)
walther@60171
   272
fun parse_vcs header pos s =
walther@60171
   273
((** )@{print} {a = "//--- ###I Fdl_Parser.parse_vcs", header = header, pos = pos, s = s};( **)
walther@60171
   274
  let
walther@60171
   275
    val line_2 = Fdl_Lexer.tokenize header Fdl_Lexer.c_comment pos s
walther@60171
   276
(** )val _ = @{print} {a = "###I Fdl_Parser.parse_vcs: ", line_2 = line_2};( **)
walther@60171
   277
    val line_3 = apsnd (filter Fdl_Lexer.is_proper) line_2
walther@60171
   278
    val line_4 = apsnd (Scan.finite Fdl_Lexer.stopper (Scan.error (!!! vcs))) line_3
walther@60171
   279
    val line_5 = apsnd fst line_4
walther@60171
   280
(** )val _ = @{print} {z = "\\--- ###I Fdl_Parser.parse_vcs \<rightarrow>", res = line_5};( **)
walther@60171
   281
  in line_5 end
walther@60171
   282
);
berghofe@41809
   283
berghofe@41809
   284
berghofe@41809
   285
(* fdl declarations, see section 4.3 of SPARK Proof Manual *)
berghofe@41809
   286
berghofe@41809
   287
datatype fdl_type =
berghofe@41809
   288
    Basic_Type of string
berghofe@41809
   289
  | Enum_Type of string list
berghofe@41809
   290
  | Array_Type of string list * string
berghofe@41809
   291
  | Record_Type of (string list * string) list
berghofe@41809
   292
  | Pending_Type;
berghofe@41809
   293
berghofe@41809
   294
(* also store items in a list to preserve order *)
berghofe@41809
   295
type 'a tab = 'a Symtab.table * (string * 'a) list;
berghofe@41809
   296
berghofe@41809
   297
fun lookup ((tab, _) : 'a tab) = Symtab.lookup tab;
berghofe@41809
   298
fun update decl (tab, items) = (Symtab.update_new decl tab, decl :: items);
berghofe@41809
   299
fun items ((_, items) : 'a tab) = rev items;
berghofe@41809
   300
berghofe@41809
   301
type decls =
berghofe@41809
   302
  {types: fdl_type tab,
berghofe@41809
   303
   vars: string tab,
berghofe@41809
   304
   consts: string tab,
berghofe@41809
   305
   funs: (string list * string) tab};
berghofe@41809
   306
berghofe@41809
   307
val empty_decls : decls =
berghofe@41809
   308
  {types = (Symtab.empty, []), vars = (Symtab.empty, []),
berghofe@41809
   309
   consts = (Symtab.empty, []), funs = (Symtab.empty, [])};
berghofe@41809
   310
berghofe@41809
   311
fun add_type_decl decl {types, vars, consts, funs} =
berghofe@41809
   312
  {types = update decl types,
berghofe@41809
   313
   vars = vars, consts = consts, funs = funs}
berghofe@41809
   314
  handle Symtab.DUP s => error ("Duplicate type " ^ s);
berghofe@41809
   315
berghofe@41809
   316
fun add_var_decl (vs, ty) {types, vars, consts, funs} =
berghofe@41809
   317
  {types = types,
berghofe@41809
   318
   vars = fold (update o rpair ty) vs vars,
berghofe@41809
   319
   consts = consts, funs = funs}
berghofe@41809
   320
  handle Symtab.DUP s => error ("Duplicate variable " ^ s);
berghofe@41809
   321
berghofe@41809
   322
fun add_const_decl decl {types, vars, consts, funs} =
berghofe@41809
   323
  {types = types, vars = vars,
berghofe@41809
   324
   consts = update decl consts,
berghofe@41809
   325
   funs = funs}
berghofe@41809
   326
  handle Symtab.DUP s => error ("Duplicate constant " ^ s);
berghofe@41809
   327
berghofe@41809
   328
fun add_fun_decl decl {types, vars, consts, funs} =
berghofe@41809
   329
  {types = types, vars = vars, consts = consts,
berghofe@41809
   330
   funs = update decl funs}
berghofe@41809
   331
  handle Symtab.DUP s => error ("Duplicate function " ^ s);
berghofe@41809
   332
wenzelm@41868
   333
fun type_decl x = ($$$ "type" |-- !!! (identifier --| $$$ "=" --
berghofe@41809
   334
  (   identifier >> Basic_Type
berghofe@41809
   335
   || $$$ "(" |-- !!! (list1 identifier --| $$$ ")") >> Enum_Type
berghofe@41809
   336
   || $$$ "array" |-- !!! ($$$ "[" |-- list1 identifier --| $$$ "]" --|
berghofe@41809
   337
        $$$ "of" -- identifier) >> Array_Type
berghofe@41809
   338
   || $$$ "record" |-- !!! (enum1 ";"
berghofe@41809
   339
        (list1 identifier -- !!! ($$$ ":" |-- identifier)) --|
berghofe@41809
   340
           $$$ "end") >> Record_Type
wenzelm@41868
   341
   || $$$ "pending" >> K Pending_Type)) >> add_type_decl) x;
berghofe@41809
   342
wenzelm@41868
   343
fun const_decl x = ($$$ "const" |-- !!! (identifier --| $$$ ":" -- identifier --|
wenzelm@41868
   344
  $$$ "=" --| $$$ "pending") >> add_const_decl) x;
berghofe@41809
   345
wenzelm@41868
   346
fun var_decl x = ($$$ "var" |-- !!! (list1 identifier --| $$$ ":" -- identifier) >>
wenzelm@41868
   347
  add_var_decl) x;
berghofe@41809
   348
wenzelm@41868
   349
fun fun_decl x = ($$$ "function" |-- !!! (identifier --
berghofe@41809
   350
  (Scan.optional ($$$ "(" |-- !!! (list1 identifier --| $$$ ")")) [] --|
wenzelm@41868
   351
   $$$ ":" -- identifier)) >> add_fun_decl) x;
berghofe@41809
   352
wenzelm@41868
   353
fun declarations x =
berghofe@47949
   354
 (the_identifier "title" |-- subprogram_kind -- identifier --| $$$ ";" --
berghofe@41809
   355
  (Scan.repeat ((type_decl || const_decl || var_decl || fun_decl) --|
wenzelm@47662
   356
     !!! ($$$ ";")) >> (fn ds => fold I ds empty_decls)) --|
wenzelm@41868
   357
  $$$ "end" --| $$$ ";") x;
berghofe@41809
   358
berghofe@41809
   359
fun parse_declarations pos s =
berghofe@41809
   360
  s |>
berghofe@41809
   361
  Fdl_Lexer.tokenize (Scan.succeed ()) Fdl_Lexer.curly_comment pos |>
berghofe@41809
   362
  snd |> filter Fdl_Lexer.is_proper |>
berghofe@41809
   363
  Scan.finite Fdl_Lexer.stopper (Scan.error (!!! declarations)) |>
berghofe@41809
   364
  fst;
berghofe@41809
   365
berghofe@41809
   366
berghofe@41809
   367
(* rules, see section 5 of SPADE Proof Checker Rules Manual *)
berghofe@41809
   368
berghofe@41809
   369
datatype fdl_rule =
berghofe@41809
   370
    Inference_Rule of expr list * expr
berghofe@41809
   371
  | Substitution_Rule of expr list * expr * expr;
berghofe@41809
   372
berghofe@41809
   373
type rules =
berghofe@41809
   374
  ((string * int) * fdl_rule) list *
berghofe@41809
   375
  (string * (expr * (string * string) list) list) list;
walther@60171
   376
val empty_rules =
walther@60171
   377
  ([]: ((string * int) * fdl_rule) list,
walther@60171
   378
   []: (string * (expr * (string * string) list) list) list);
berghofe@41809
   379
berghofe@41809
   380
val condition_list = $$$ "[" |-- list expression --| $$$ "]";
berghofe@41809
   381
val if_condition_list = $$$ "if" |-- !!! condition_list;
berghofe@41809
   382
berghofe@41809
   383
val rule =
berghofe@41809
   384
  identifier -- !!! ($$$ "(" |-- number --| $$$ ")" --| $$$ ":" --
berghofe@41809
   385
  (expression :|-- (fn e =>
berghofe@41809
   386
        $$$ "may_be_deduced" >> K (Inference_Rule ([], e))
berghofe@41809
   387
     || $$$ "may_be_deduced_from" |--
berghofe@41809
   388
          !!! condition_list >> (Inference_Rule o rpair e)
berghofe@41809
   389
     || $$$ "may_be_replaced_by" |-- !!! (expression --
berghofe@41809
   390
          Scan.optional if_condition_list []) >> (fn (e', cs) =>
berghofe@41809
   391
            Substitution_Rule (cs, e, e'))
berghofe@41809
   392
     || $$$ "&" |-- !!! (expression --| $$$ "are_interchangeable" --
berghofe@41809
   393
          Scan.optional if_condition_list []) >> (fn (e', cs) =>
berghofe@41809
   394
            Substitution_Rule (cs, e, e')))) --| $$$ ".") >>
berghofe@41809
   395
    (fn (id, (n, rl)) => ((id, n), rl));
berghofe@41809
   396
berghofe@41809
   397
val rule_family = 
berghofe@41809
   398
  $$$ "rule_family" |-- identifier --| $$$ ":" --
berghofe@41809
   399
  enum1 "&" (expression -- !!! ($$$ "requires" |-- $$$ "[" |--
berghofe@41809
   400
    list (identifier -- !!! ($$$ ":" |-- identifier)) --| $$$ "]")) --|
berghofe@41809
   401
  $$$ ".";
berghofe@41809
   402
berghofe@41809
   403
val rules =
berghofe@41809
   404
  parse_all (rule >> (apfst o cons) || rule_family >> (apsnd o cons)) >>
wenzelm@47662
   405
  (fn rls => fold_rev I rls ([], []));
berghofe@41809
   406
berghofe@41809
   407
fun parse_rules pos s =
berghofe@41809
   408
  s |>
berghofe@41809
   409
  Fdl_Lexer.tokenize (Scan.succeed ())
berghofe@41809
   410
    (Fdl_Lexer.c_comment || Fdl_Lexer.percent_comment) pos |>
berghofe@41809
   411
  snd |> filter Fdl_Lexer.is_proper |>
berghofe@41809
   412
  Scan.finite Fdl_Lexer.stopper (Scan.error (!!! rules)) |>
berghofe@41809
   413
  fst;
berghofe@41809
   414
berghofe@41809
   415
end;