src/HOL/TPTP/TPTP_Parser/tptp_problem_name.ML
changeset 46844 5d9aab0c609c
child 47520 ef2d04520337
equal deleted inserted replaced
46843:8d5d255bf89c 46844:5d9aab0c609c
       
     1 (*  Title:      HOL/TPTP/TPTP_Parser/tptp_problem_name.ML
       
     2     Author:     Nik Sultana, Cambridge University Computer Laboratory
       
     3 
       
     4 Scans a TPTP problem name. Naming convention is described
       
     5 http://www.cs.miami.edu/~tptp/TPTP/TR/TPTPTR.shtml#Problem and Axiomatization Naming
       
     6 *)
       
     7 
       
     8 signature TPTP_PROBLEM_NAME =
       
     9 sig
       
    10   datatype suffix =
       
    11       Problem of
       
    12         ((*version*)int *
       
    13         (*size parameter*)int option) *
       
    14         (*extension*)string
       
    15     | Axiom of
       
    16         (*specialisation*)int *
       
    17         (*extension*)string
       
    18 
       
    19   type tptp_problem_name =
       
    20     {prob_domain : string,
       
    21      prob_number : int,
       
    22      prob_form : TPTP_Syntax.language,
       
    23      suffix : suffix}
       
    24 
       
    25   datatype problem_name =
       
    26       Standard of tptp_problem_name
       
    27     | Nonstandard of string
       
    28 
       
    29   exception TPTP_PROBLEM_NAME of string
       
    30 
       
    31   val parse_problem_name : string -> problem_name
       
    32   val mangle_problem_name : problem_name -> string
       
    33 end
       
    34 
       
    35 structure TPTP_Problem_Name: TPTP_PROBLEM_NAME =
       
    36 struct
       
    37 
       
    38 (*some basic tokens*)
       
    39 val numerics = map Char.chr (48 upto 57) (*0..9*)
       
    40 val alphabetics =
       
    41   map Char.chr (65 upto 90) @ (*A..Z*)
       
    42   map Char.chr (97 upto 122)  (*a..z*)
       
    43 (*TPTP formula forms*)
       
    44 val forms = [#"^", #"_", #"=", #"+", #"-"]
       
    45 
       
    46 (*lift a list of characters into a scanner combinator matching any one of the
       
    47 characters in that list.*)
       
    48 fun lift l =
       
    49   (map (Char.toString #> ($$)) l, Scan.fail)
       
    50   |-> fold (fn x => fn y => x || y)
       
    51 
       
    52 (*combinators for parsing letters and numbers*)
       
    53 val alpha = lift alphabetics
       
    54 val numer = lift numerics
       
    55 
       
    56 datatype suffix =
       
    57     Problem of
       
    58       ((*version*)int *
       
    59       (*size parameter*)int option) *
       
    60       (*extension*)string
       
    61   | Axiom of
       
    62       (*specialisation*)int *
       
    63       (*extension*)string
       
    64 
       
    65 val to_int = Int.fromString #> the
       
    66 val rm_ending = Scan.this_string "rm"
       
    67 val ax_ending =
       
    68   ((numer >> to_int) --|
       
    69    $$ "." -- (Scan.this_string "eq" || Scan.this_string "ax" || rm_ending))
       
    70   >> Axiom
       
    71 val prob_ending = $$ "p" || $$ "g" || rm_ending
       
    72 val prob_suffix =
       
    73   ((numer >> to_int) --
       
    74    Scan.option ($$ "." |-- numer ^^ numer ^^ numer >> to_int) --| $$ "."
       
    75    -- prob_ending)
       
    76   >> Problem
       
    77 
       
    78 type tptp_problem_name =
       
    79   {prob_domain : string,
       
    80    prob_number : int,
       
    81    prob_form : TPTP_Syntax.language,
       
    82    suffix : suffix}
       
    83 
       
    84 datatype problem_name =
       
    85     Standard of tptp_problem_name
       
    86   | Nonstandard of string
       
    87 
       
    88 exception TPTP_PROBLEM_NAME of string
       
    89 
       
    90 (*FIXME add graceful handling on non-wellformed TPTP filenames*)
       
    91 fun parse_problem_name str' : problem_name =
       
    92   let
       
    93     val str = Symbol.explode str'
       
    94     (*NOTE there's an ambiguity in the spec: there's no way of knowing if a
       
    95     file ending in "rm" used to be "ax" or "p". Here we default to "p".*)
       
    96     val ((((prob_domain, prob_number), prob_form), suffix), rest) =
       
    97      Scan.finite Symbol.stopper
       
    98      ((alpha ^^ alpha ^^ alpha) --
       
    99      (numer ^^ numer ^^ numer >> to_int) --
       
   100      lift forms -- (prob_suffix || ax_ending)) str
       
   101 
       
   102     fun parse_form str =
       
   103       case str of
       
   104         "^" => TPTP_Syntax.THF
       
   105       | "_" => TPTP_Syntax.TFF
       
   106       | "=" => TPTP_Syntax.TFF_with_arithmetic
       
   107       | "+" => TPTP_Syntax.FOF
       
   108       | "-" => TPTP_Syntax.CNF
       
   109       | _ => raise TPTP_PROBLEM_NAME ("Unknown TPTP form: " ^ str)
       
   110   in
       
   111     if null rest (*check if the whole name was parsed*)
       
   112     then
       
   113       Standard
       
   114         {prob_domain = prob_domain,
       
   115          prob_number = prob_number,
       
   116          prob_form = parse_form prob_form,
       
   117          suffix = suffix}
       
   118       handle _ => Nonstandard str'
       
   119     else raise TPTP_PROBLEM_NAME ("Parse error")
       
   120   end
       
   121 
       
   122 (*Produces an ASCII encoding of a TPTP problem-file name.*)
       
   123 fun mangle_problem_name (prob : problem_name) : string =
       
   124   case prob of
       
   125      Standard tptp_prob =>
       
   126        let
       
   127          val prob_form =
       
   128            case #prob_form tptp_prob of
       
   129              TPTP_Syntax.THF => "_thf_"
       
   130            | TPTP_Syntax.TFF => "_tff_"
       
   131            | TPTP_Syntax.TFF_with_arithmetic => "_thfwa_"
       
   132            | TPTP_Syntax.FOF => "_fof_"
       
   133            | TPTP_Syntax.CNF => "_cnf_"
       
   134          val suffix =
       
   135            case #suffix tptp_prob of
       
   136              Problem ((version, size), extension) =>
       
   137                Int.toString version ^ "_" ^
       
   138                (if is_some size then Int.toString (the size) ^ "_" else "") ^
       
   139                extension
       
   140            | Axiom (specialisation, extension) =>
       
   141                Int.toString specialisation ^ "_" ^ extension
       
   142        in
       
   143          #prob_domain tptp_prob ^
       
   144          Int.toString (#prob_number tptp_prob) ^
       
   145          prob_form ^
       
   146          suffix
       
   147        end
       
   148    | Nonstandard str => str
       
   149 
       
   150 end