(* Parsercomb -- parser combinators *) signature Parsercomb = sig type 'elm stream type ('elm, 'res) parser = 'elm stream -> ('res * 'elm stream) option exception Parse of string val stream : ('src -> ('elm * 'src) option) -> 'src -> 'elm stream val -- : ('a, 'b) parser * ('a, 'c) parser -> ('a, 'b * 'c) parser val || : ('a, 'b) parser * ('a, 'b) parser -> ('a, 'b) parser val >> : ('a, 'b) parser * ('b -> 'c) -> ('a, 'c) parser val >>* : ('a, 'b) parser * ('b -> 'c option) -> ('a, 'c) parser val >>= : ('a, 'b) parser * ('b -> ('a, 'c) parser) -> ('a, 'c) parser val #-- : ('elm, 'a) parser * ('elm, 'b) parser -> ('elm, 'b) parser val --# : ('elm, 'a) parser * ('elm, 'b) parser -> ('elm, 'a) parser val $-- : string * (char, 'a) parser -> (char, 'a) parser val --$ : (char, 'a) parser * string -> (char, 'a) parser val repeat0 : ('elm, 'res) parser -> ('elm, 'res list) parser val repeat1 : ('elm, 'res) parser -> ('elm, 'res * 'res list) parser val optional : ('elm, 'res) parser -> ('elm, 'res option) parser val getItem : ('elm, 'elm) parser val failure : ('elm, 'res) parser val success : 'res -> ('elm, 'res) parser val eof : 'res -> ('elm, 'res) parser val $# : char -> (char, char) parser val $ : string -> (char, string) parser val getLit : ''elm -> (''elm, ''elm) parser val getChar : (char -> bool) -> (char, char) parser val getChars0 : (char -> bool) -> (char, string) parser val getChars1 : (char -> bool) -> (char, string) parser val getElem : ('elm -> bool) -> ('elm, 'elm) parser val getElems0 : ('elm -> bool) -> ('elm, 'elm list) parser val getElems1 : ('elm -> bool) -> ('elm, 'elm * 'elm list) parser val commitChar : string -> (char, 'res) parser -> (char, 'res) parser val commitElem : string -> ('elm -> string) -> ('elm, 'res) parser -> ('elm, 'res) parser (* Applying a parser to a stream *) val parse : ('elm, 'res) parser -> 'elm stream -> 'res option val scan : (('a, 'a stream) StringCvt.reader -> 'a stream -> 'b) -> 'a stream -> 'b val skipWS : (char, 'res) parser -> (char, 'res) parser val scanString : (char, 'res) parser -> string -> 'res option val scanSubstr : (char, 'res) parser -> substring -> 'res option val scanList : ('elm, 'res) parser -> 'elm list -> 'res option end (* ['elm stream] is the type of a lazy streams (sequences) of 'elm values. [('elm, 'res) parser] is the type of parsers that consume elements from an 'elm stream to produce a result of type 'res. The attempt may succeed with a result of type 'res, in which case the parser may have consumed elements of the stream, or it may fail, in which case the 'elm stream remains unchanged. Below we indicate those parsers that are guaranteed to consume from the stream if they succeed. Such parsers can be safely used as the argument to e.g. the repeat0 and repeat1 parser-transformers. [stream getc src] builds a stream from a reader getc and a stream state src. [par1 -- par2] succeeds with (r1, r2) if par1 succeeds with r1 and then par2 succeeds with r2 on the remainder of the stream. [par1 || par2] succeeds with r1 if par1 succeeds with r1 on stream; otherwise succeeds with r2 if par2 succeeds with r2 on stream; otherwise fails. [par >> f] succeeds with f(r) if par succeeds with r on the stream. [par >>* f] succeeds with y if par succeeds with r on the stream, and f r = SOME y; fails otherwise. [par1 >>= parf2] succeeds with r2 if par1 succeeds with r1 and then (parf2 r1) succeeds with r2 on the remainder of the stream. [par1 #-- par2] succeeds with r2 if par1 succeeds with r1 and then par2 succeeds with r2 on the remainder of the stream. [par1 --# par2] succeeds with r1 if par1 succeeds with r1 and then par2 succeeds with r2 on the remainder of the stream. [s $-- par] succeeds with r if the stream begins with the characters of the string s, and par succeeds with r on the remainder of the stream. [par $-- s] succeeds with r if p succeeds with r, and then the remainder of the stream begins with the characters of the string s. Recommended fixities: infix 6 $-- --$ #-- --# infix 5 -- infix 3 >> >>* infix 2 >>= infix 0 || [repeat0 par] succeeds with [r1, r2, ..., rn] if par succeeds with r1, and then par succeeds with r2 on the remainder of the stream, and then par succeeds with r3 on the remainder, etc, for some n>=0. May succeed without consuming from the stream, even if par must consume from the stream to succeed. [repeat1 par] succeeds with (r1, [r2, ..., rn]) if par succeeds with r1, and then par succeeds with r2 on the remainder of the stream, and then par succeeds with r3 on the remainder, etc, for some n>=1. Must consume from the stream to succeed, provided par must consume from the stream to succeed. Equivalent to par -- repeat0 par [optional par] succeeds with SOME(r) if par succeeds with r; succeeds with NONE otherwise. May succeed without consuming from the stream. Equivalent to par || succeed NONE [success v] always succeeds with v, consuming nothing from the stream. [failure] always fails. [getItem] succeeds with r if the stream is non-empty and its first element is r; fails otherwise. Must consume from the stream if it succeeds. [eof v] succeeds with v if the stream is empty (end of file); fails otherwise. [$# c] succeeds with c if the stream begins with character c. Consumes from the stream if it succeeds. [$ s] succeeds with s if the stream begins with string s. Consumes from the stream if it succeeds. [getChar p] succeeds with c if the first character c of the stream satisfies predicate p. Consumes from the stream if it succeeds. [getChars0 p] always succeeds with s, where s is the longest prefix of the stream all of whose characters satisfy predicate p. May succeed without consuming from the stream. Equivalent to repeat0 (getChar p) >> String.implode [getChars1 p] succeeds with s, where s is the longest non-empty prefix of the stream all of whose characters satisfy predicate p, if such a prefix exists; fails if the first character of the stream does not satisfy p. Consumes from the stream if it succeeds. Equivalent to repeat1 (getChar p) >> op:: >> String.implode [getLit elm] succeeds with elm if the first element of the stream equals elm; fails otherwise. Consumes from the stream if it succeeds. [getElem p] succeeds with elm if the first element elm of the stream satisfies predicate p. Consumes from the stream if it succeeds. [getElems0 p] always succeeds with elms, where elms is the longest prefix of the stream all of whose elements satisfy predicate p. May succeed without consuming from the stream. Equivalent to repeat0 (getElem pred) strm [getElems1 p] succeeds with (elm1, elmr), where elm1::elmr is the longest non-empty prefix of the stream all of whose elements satisfy predicate p; fails if the first element of the stream does not satisfy p. Consumes from the stream if it succeeds. Equivalent to repeat1 (getElem pred) strm [commitChar cexpd par] succeeds with r if par succeeds with r; raises exception Parse otherwise. The exception's string argument will have the form Expected but found at character number n where cfound is the first character of the stream to which commitChar is applied, or the text "eof" if that stream is empty, and n is the number of the stream character cfound counting from the beginning of the stream. The first character has number 0. [commitElem eexpd showe par] succeeds with r if par succeeds with r; raises exception Parse otherwise. The exception's string argument will have the form Expected but found at element number n where efound is the result of applying showe to the first element of the stream, or the text "eof" if the stream is empty, and n is the number of stream element efound counting from the beginning of the stream. The first element has number 0. [parse par strm] applies the parser par to the stream strm. Returns SOME(v) if the parser succeeds with v; returns NONE otherwise. [scan scfn] produces a parser corresponding to the scan function scfn. Typical examples are: scan Bool.scan : (char, bool) parser scan Date.scan : (char, Date.date) parser scan Real.scan : (char, real) parser scan Time.scan : (char, Time.time) parser scan (Int.scan StringCvt.DEC) : (char, int) parser scan (Word.scan StringCvt.HEX) : (char, Word.word) parser scan (Word8.scan StringCvt.HEX) : (char, Word8.word) parser For instance, one may produce a list of real numbers by parsing space-separated real numerals from a string s: scanString (repeat0 (getChars0 Char.isSpace #-- scan Real.scan)) s [skipWS par] removes any leading whitespace from the stream and then applies par to the remainder. [scanSubstring par sus] applies the parser par to the stream of characters taken from the substring sus. Returns SOME v if par succeeds with v; returns NONE otherwise. Equivalent to parse par (stream Substring.getc sus) [scanString par s] applies the parser par to the stream of characters taken from the string s. Returns SOME v if par succeeds with v; returns NONE otherwise. Example: Parsing an integer numeral from the string "723984626junk": val intphr = getChars1 Char.isDigit val i : string option = scanString intphr "723984626junk" [scanList phr xs] applies the parser par to the stream of elements from the list xs. Returns SOME v if par succeeds with v; returns NONE otherwise. Equivalent to parse par (stream List.getItem cs) *)