diff options
-rw-r--r-- | stdlib/scanf.ml | 28 | ||||
-rw-r--r-- | stdlib/scanf.mli | 43 |
2 files changed, 45 insertions, 26 deletions
diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml index 92d3d667d..aef85182a 100644 --- a/stdlib/scanf.ml +++ b/stdlib/scanf.ml @@ -306,10 +306,13 @@ end;; (* Formatted input functions. *) +type ('a, 'b, 'c, 'd) tscanf = + ('a, Scanning.scanbuf, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c;; + module Sformat = Printf.Sformat;; external string_to_format : - string -> ('a, 'b, 'c, 'd) format4 = "%identity";; + string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity";; (* Reporting errors. *) exception Scan_failure of string;; @@ -962,7 +965,7 @@ let rec skip_whites ib = If the scanning or some conversion fails, the main scanning function aborts and applies the scanning buffer and a string that explains the error to the error handling function [ef] (the error continuation). *) -let kscanf ib ef fmt f = +let kscanf ib ef fmt = Obj.magic (fun f -> let lim = Sformat.length fmt - 1 in @@ -997,7 +1000,7 @@ let kscanf ib ef fmt f = | 'S' -> let _x = scan_String max ib in scan_fmt (stack f (token_string ib)) (succ i) - | '[' -> + | '[' (* ']' *) -> let i, char_set = read_char_set fmt (succ i) in let i, stp = scan_fmt_stoppers (succ i) in let _x = scan_chars_in_char_set stp char_set max ib in @@ -1061,7 +1064,7 @@ let kscanf ib ef fmt f = let p, i = read_width 0 (succ i) in scan_conversion skip (succ (max + p)) f i | _ -> scan_conversion skip max f i end - | '(' | '{' as conv -> + | '(' | '{' as conv (* ')' '}' *) -> let i = succ i in let j = Printf.sub_format @@ -1070,7 +1073,7 @@ let kscanf ib ef fmt f = let _x = scan_String max ib in let rf = token_string ib in if not (compatible_format_type rf mf) then format_mismatch rf mf ib else - if conv = '{' then scan_fmt (stack f rf) j else + if conv = '{' (* '}' *) then scan_fmt (stack f rf) j else let nf = scan_fmt (Obj.magic rf) 0 in scan_fmt (stack f nf) j | c -> bad_conversion fmt i c @@ -1088,7 +1091,7 @@ let kscanf ib ef fmt f = try scan_fmt (fun () -> f) 0 with | (Scan_failure _ | Failure _ | End_of_file) as exc -> stack (delay ef ib) exc in - return v;; + return v);; let bscanf ib = kscanf ib scanf_bad_input;; @@ -1103,9 +1106,16 @@ let bscanf_format ib fmt f = let fmt1 = ignore (scan_String max_int ib); token_string ib in if not (compatible_format_type fmt1 fmt) then format_mismatch fmt1 fmt ib else - let fresh_fmt1 = String.copy fmt1 in - f (string_to_format fresh_fmt1);; + f (string_to_format fmt1);; let sscanf_format s fmt f = bscanf_format (Scanning.from_string s) fmt f;; -let format_from_string s fmt = sscanf_format s fmt (fun x -> x);; +let quote_string s = + let b = Buffer.create (String.length s + 2) in + Buffer.add_char b '\"'; + Buffer.add_string b s; + Buffer.add_char b '\"'; + Buffer.contents b;; + +let format_from_string s fmt = + sscanf_format (quote_string s) fmt (fun x -> x);; diff --git a/stdlib/scanf.mli b/stdlib/scanf.mli index 37fe47dda..aaa447de8 100644 --- a/stdlib/scanf.mli +++ b/stdlib/scanf.mli @@ -85,9 +85,12 @@ exception Scan_failure of string;; (** The exception that formatted input functions raise when the input cannot be read according to the given format. *) -val bscanf : - Scanning.scanbuf -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;; -(** [bscanf ib fmt f] reads tokens from the scanning buffer [ib] according +type ('a, 'b, 'c, 'd) tscanf = + ('a, Scanning.scanbuf, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c;; + +val bscanf : Scanning.scanbuf -> ('a, 'b, 'c, 'd) tscanf;; +(** + [bscanf ib fmt f] reads tokens from the scanning buffer [ib] according to the format string [fmt], converts these tokens to values, and applies the function [f] to these values. The result of this application of [f] is the result of the whole construct. @@ -160,6 +163,9 @@ val bscanf : first character of the range (or just after the [^] in case of range negation); hence [\[\]\]] matches a [\]] character and [\[^\]\]] matches any character that is not [\]]. + - [r]: user-defined reader. Takes a reader function [rdr] as argument and + applies it to [ib]. The argument [rdr] must therefore have type + [Scanf.Scanning.scanbuf -> 't] and the argument read has type ['t]. - [\{ fmt %\}]: reads a format string argument to the format specified by the internal format [fmt]. The format string to be read must have the same type as the internal format [fmt]. @@ -232,7 +238,7 @@ val bscanf : [ocamlyacc]-generated parsers. *) -val fscanf : in_channel -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;; +val fscanf : in_channel -> ('a, 'b, 'c, 'd) tscanf;; (** Same as {!Scanf.bscanf}, but inputs from the given channel. Warning: since all scanning functions operate from a scanning @@ -251,16 +257,16 @@ val fscanf : in_channel -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;; This method is not only clearer it is also faster, since scanning buffers to files are optimized for fast bufferized reading. *) -val sscanf : string -> ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;; +val sscanf : string -> ('a, 'b, 'c, 'd) tscanf;; (** Same as {!Scanf.bscanf}, but inputs from the given string. *) -val scanf : ('a, Scanning.scanbuf, 'b) format -> 'a -> 'b;; +val scanf : ('a, 'b, 'c, 'd) tscanf;; (** Same as {!Scanf.bscanf}, but reads from the predefined scanning buffer {!Scanf.Scanning.stdib} that is connected to [stdin]. *) val kscanf : - Scanning.scanbuf -> (Scanning.scanbuf -> exn -> 'a) -> - ('b, Scanning.scanbuf, 'a) format -> 'b -> 'a;; + Scanning.scanbuf -> (Scanning.scanbuf -> exn -> 'd) -> + ('a, 'b, 'c, 'd) tscanf;; (** Same as {!Scanf.bscanf}, but takes an additional function argument [ef] that is called in case of error: if the scanning process or some conversion fails, the scanning function aborts and applies the @@ -268,20 +274,23 @@ val kscanf : exception that aborted the scanning process. *) val bscanf_format : - Scanning.scanbuf -> ('a, 'b, 'c, 'd) format4 -> - (('a, 'b, 'c, 'd) format4 -> 'e) -> 'e;; + Scanning.scanbuf -> ('a, 'b, 'c, 'd, 'e, 'f) format6 -> + (('a, 'b, 'c, 'd, 'e, 'f) format6 -> 'g) -> 'g;; (** [bscanf_format ib fmt f] reads a format string token from scannning buffer - [ib], according to the format string [fmt], and applies the function [f] to - the resulting format string value. + [ib], according to the given format string [fmt], and applies + the function [f] to the resulting format string value. Raises [Scan_failure] if the format string value read has not the same type as [fmt]. *) val sscanf_format : - string -> ('a, 'b, 'c, 'd) format4 -> - (('a, 'b, 'c, 'd) format4 -> 'e) -> 'e;; + string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 -> + (('a, 'b, 'c, 'd, 'e, 'f) format6 -> 'g) -> 'g;; (** Same as {!Scanf.bscanf_format}, but inputs from the given string. *) val format_from_string : - string -> ('a, 'b, 'c, 'd) format4 -> ('a, 'b, 'c, 'd) format4;; -(** Same as {!Scanf.sscanf_format}, but converts the given string to a format - string. *) + string -> + ('a, 'b, 'c, 'd, 'e, 'f) format6 -> ('a, 'b, 'c, 'd, 'e, 'f) format6;; +(** [format_from_string s fmt] converts a string argument to a format string, + according to the given format string [fmt]. + Raises [Scan_failure] if [s], considered as a format string, has not the same + type as [fmt]. *) |