src/Pure/General/scan.ML
changeset 58850 1bb0ad7827b4
parent 55104 8284c0d5bf52
child 58864 505a8150368a
equal deleted inserted replaced
58849:ef7700ecce83 58850:1bb0ad7827b4
    36 end;
    36 end;
    37 
    37 
    38 signature SCAN =
    38 signature SCAN =
    39 sig
    39 sig
    40   include BASIC_SCAN
    40   include BASIC_SCAN
    41   val prompt: string -> ('a -> 'b) -> 'a -> 'b
       
    42   val permissive: ('a -> 'b) -> 'a -> 'b
    41   val permissive: ('a -> 'b) -> 'a -> 'b
    43   val error: ('a -> 'b) -> 'a -> 'b
    42   val error: ('a -> 'b) -> 'a -> 'b
    44   val catch: ('a -> 'b) -> 'a -> 'b    (*exception Fail*)
    43   val catch: ('a -> 'b) -> 'a -> 'b    (*exception Fail*)
    45   val fail: 'a -> 'b
    44   val fail: 'a -> 'b
    46   val fail_with: ('a -> message) -> 'a -> 'b
    45   val fail_with: ('a -> message) -> 'a -> 'b
    74   val is_stopper: 'a stopper -> 'a -> bool
    73   val is_stopper: 'a stopper -> 'a -> bool
    75   val finite': 'a stopper -> ('b * 'a list -> 'c * ('d * 'a list))
    74   val finite': 'a stopper -> ('b * 'a list -> 'c * ('d * 'a list))
    76     -> 'b * 'a list -> 'c * ('d * 'a list)
    75     -> 'b * 'a list -> 'c * ('d * 'a list)
    77   val finite: 'a stopper -> ('a list -> 'b * 'a list) -> 'a list -> 'b * 'a list
    76   val finite: 'a stopper -> ('a list -> 'b * 'a list) -> 'a list -> 'b * 'a list
    78   val read: 'a stopper -> ('a list -> 'b * 'a list) -> 'a list -> 'b option
    77   val read: 'a stopper -> ('a list -> 'b * 'a list) -> 'a list -> 'b option
    79   val drain: string -> (string -> 'a -> 'b list * 'a) -> 'b stopper ->
    78   val drain: ('a -> 'b list * 'a) -> 'b stopper -> ('c * 'b list -> 'd * ('e * 'b list)) ->
    80     ('c * 'b list -> 'd * ('e * 'b list)) -> ('c * 'b list) * 'a -> ('d * ('e * 'b list)) * 'a
    79     ('c * 'b list) * 'a -> ('d * ('e * 'b list)) * 'a
    81   type lexicon
    80   type lexicon
    82   val is_literal: lexicon -> string list -> bool
    81   val is_literal: lexicon -> string list -> bool
    83   val literal: lexicon -> (string * 'a) list -> (string * 'a) list * (string * 'a) list
    82   val literal: lexicon -> (string * 'a) list -> (string * 'a) list * (string * 'a) list
    84   val empty_lexicon: lexicon
    83   val empty_lexicon: lexicon
    85   val extend_lexicon: string list -> lexicon -> lexicon
    84   val extend_lexicon: string list -> lexicon -> lexicon
    96 
    95 
    97 (* exceptions *)
    96 (* exceptions *)
    98 
    97 
    99 type message = unit -> string;
    98 type message = unit -> string;
   100 
    99 
   101 exception MORE of string option;        (*need more input (prompt)*)
   100 exception MORE of unit;  (*need more input*)
   102 exception FAIL of message option;       (*try alternatives (reason of failure)*)
   101 exception FAIL of message option;  (*try alternatives (reason of failure)*)
   103 exception ABORT of message;             (*dead end*)
   102 exception ABORT of message;  (*dead end*)
   104 
   103 
   105 fun !! err scan xs = scan xs handle FAIL msg => raise ABORT (err (xs, msg));
   104 fun !! err scan xs = scan xs handle FAIL msg => raise ABORT (err (xs, msg));
   106 fun permissive scan xs = scan xs handle MORE _ => raise FAIL NONE | ABORT _ => raise FAIL NONE;
   105 fun permissive scan xs = scan xs handle MORE () => raise FAIL NONE | ABORT _ => raise FAIL NONE;
   107 fun strict scan xs = scan xs handle MORE _ => raise FAIL NONE;
   106 fun strict scan xs = scan xs handle MORE () => raise FAIL NONE;
   108 fun prompt str scan xs = scan xs handle MORE NONE => raise MORE (SOME str);
       
   109 fun error scan xs = scan xs handle ABORT msg => Library.error (msg ());
   107 fun error scan xs = scan xs handle ABORT msg => Library.error (msg ());
   110 
   108 
   111 fun catch scan xs = scan xs
   109 fun catch scan xs = scan xs
   112   handle ABORT msg => raise Fail (msg ())
   110   handle ABORT msg => raise Fail (msg ())
   113     | FAIL msg => raise Fail (case msg of NONE => "Syntax error" | SOME m => m ());
   111     | FAIL msg => raise Fail (case msg of NONE => "Syntax error" | SOME m => m ());
   138 
   136 
   139 fun fail _ = raise FAIL NONE;
   137 fun fail _ = raise FAIL NONE;
   140 fun fail_with msg_of xs = raise FAIL (SOME (msg_of xs));
   138 fun fail_with msg_of xs = raise FAIL (SOME (msg_of xs));
   141 fun succeed y xs = (y, xs);
   139 fun succeed y xs = (y, xs);
   142 
   140 
   143 fun some _ [] = raise MORE NONE
   141 fun some _ [] = raise MORE ()
   144   | some f (x :: xs) =
   142   | some f (x :: xs) =
   145       (case f x of SOME y => (y, xs) | _ => raise FAIL NONE);
   143       (case f x of SOME y => (y, xs) | _ => raise FAIL NONE);
   146 
   144 
   147 fun one _ [] = raise MORE NONE
   145 fun one _ [] = raise MORE ()
   148   | one pred (x :: xs) =
   146   | one pred (x :: xs) =
   149       if pred x then (x, xs) else raise FAIL NONE;
   147       if pred x then (x, xs) else raise FAIL NONE;
   150 
   148 
   151 fun $$ a = one (fn s: string => s = a);
   149 fun $$ a = one (fn s: string => s = a);
   152 fun ~$$ a = one (fn s: string => s <> a);
   150 fun ~$$ a = one (fn s: string => s <> a);
   153 
   151 
   154 fun this ys xs =
   152 fun this ys xs =
   155   let
   153   let
   156     fun drop_prefix [] xs = xs
   154     fun drop_prefix [] xs = xs
   157       | drop_prefix (_ :: _) [] = raise MORE NONE
   155       | drop_prefix (_ :: _) [] = raise MORE ()
   158       | drop_prefix (y :: ys) (x :: xs) =
   156       | drop_prefix (y :: ys) (x :: xs) =
   159           if (y: string) = x then drop_prefix ys xs else raise FAIL NONE;
   157           if (y: string) = x then drop_prefix ys xs else raise FAIL NONE;
   160   in (ys, drop_prefix ys xs) end;
   158   in (ys, drop_prefix ys xs) end;
   161 
   159 
   162 fun this_string s = this (raw_explode s) >> K s;  (*primitive string -- no symbols here!*)
   160 fun this_string s = this (raw_explode s) >> K s;  (*primitive string -- no symbols here!*)
   163 
   161 
   164 fun many _ [] = raise MORE NONE
   162 fun many _ [] = raise MORE ()
   165   | many pred (lst as x :: xs) =
   163   | many pred (lst as x :: xs) =
   166       if pred x then apfst (cons x) (many pred xs)
   164       if pred x then apfst (cons x) (many pred xs)
   167       else ([], lst);
   165       else ([], lst);
   168 
   166 
   169 fun many1 pred = one pred ::: many pred;
   167 fun many1 pred = one pred ::: many pred;
   263   | _ => NONE);
   261   | _ => NONE);
   264 
   262 
   265 
   263 
   266 (* infinite scans -- draining state-based source *)
   264 (* infinite scans -- draining state-based source *)
   267 
   265 
   268 fun drain def_prompt get stopper scan ((state, xs), src) =
   266 fun drain get stopper scan ((state, xs), src) =
   269   (scan (state, xs), src) handle MORE prompt =>
   267   (scan (state, xs), src) handle MORE () =>
   270     (case get (the_default def_prompt prompt) src of
   268     (case get src of
   271       ([], _) => (finite' stopper scan (state, xs), src)
   269       ([], _) => (finite' stopper scan (state, xs), src)
   272     | (xs', src') => drain def_prompt get stopper scan ((state, xs @ xs'), src'));
   270     | (xs', src') => drain get stopper scan ((state, xs @ xs'), src'));
   273 
   271 
   274 
   272 
   275 
   273 
   276 (** datatype lexicon -- position tree **)
   274 (** datatype lexicon -- position tree **)
   277 
   275 
   290 
   288 
   291 fun literal lexicon =
   289 fun literal lexicon =
   292   let
   290   let
   293     fun finish (SOME (res, rest)) = (rev res, rest)
   291     fun finish (SOME (res, rest)) = (rev res, rest)
   294       | finish NONE = raise FAIL NONE;
   292       | finish NONE = raise FAIL NONE;
   295     fun scan _ res (Lexicon tab) [] = if Symtab.is_empty tab then finish res else raise MORE NONE
   293     fun scan _ res (Lexicon tab) [] =
       
   294           if Symtab.is_empty tab then finish res else raise MORE ()
   296       | scan path res (Lexicon tab) (c :: cs) =
   295       | scan path res (Lexicon tab) (c :: cs) =
   297           (case Symtab.lookup tab (fst c) of
   296           (case Symtab.lookup tab (fst c) of
   298             SOME (tip, lex) =>
   297             SOME (tip, lex) =>
   299               let val path' = c :: path
   298               let val path' = c :: path
   300               in scan path' (if tip then SOME (path', cs) else res) lex cs end
   299               in scan path' (if tip then SOME (path', cs) else res) lex cs end