(*---------------------------------------------------------------------------- Copyright (c) 2016 Inhabited Type LLC. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------*) (** Parser combinators built for speed and memory-efficiency. Angstrom is a parser-combinator library that provides monadic and applicative interfaces for constructing parsers with unbounded lookahead. Its parsers can consume input incrementally, whether in a blocking or non-blocking environment. To achieve efficient incremental parsing, Angstrom offers both a buffered and unbuffered interface to input streams, with the {!module:Unbuffered} interface enabling zero-copy IO. With these features and low-level iteration parser primitives like {!take_while} and {!skip_while}, Angstrom makes it easy to write efficient, expressive, and reusable parsers suitable for high-performance applications. *) type +'a t (** A parser for values of type ['a]. *) type bigstring = Bigstringaf.t (** {2 Basic parsers} *) val peek_char : char option t (** [peek_char] accepts any char and returns it, or returns [None] if the end of input has been reached. This parser does not advance the input. Use it for lookahead. *) val peek_char_fail : char t (** [peek_char_fail] accepts any char and returns it. If end of input has been reached, it will fail. This parser does not advance the input. Use it for lookahead. *) val peek_string : int -> string t (** [peek_string n] accepts exactly [n] characters and returns them as a string. If there is not enough input, it will fail. This parser does not advance the input. Use it for lookahead. *) val char : char -> char t (** [char c] accepts [c] and returns it. *) val not_char : char -> char t (** [not_char] accepts any character that is not [c] and returns the matched character. *) val any_char : char t (** [any_char] accepts any character and returns it. *) val satisfy : (char -> bool) -> char t (** [satisfy f] accepts any character for which [f] returns [true] and returns the accepted character. In the case that none of the parser succeeds, then the parser will fail indicating the offending character. *) val string : string -> string t (** [string s] accepts [s] exactly and returns it. *) val string_ci : string -> string t (** [string_ci s] accepts [s], ignoring case, and returns the matched string, preserving the case of the original input. *) val skip : (char -> bool) -> unit t (** [skip f] accepts any character for which [f] returns [true] and discards the accepted character. [skip f] is equivalent to [satisfy f] but discards the accepted character. *) val skip_while : (char -> bool) -> unit t (** [skip_while f] accepts input as long as [f] returns [true] and discards the accepted characters. *) val take : int -> string t (** [take n] accepts exactly [n] characters of input and returns them as a string. *) val take_while : (char -> bool) -> string t (** [take_while f] accepts input as long as [f] returns [true] and returns the accepted characters as a string. This parser does not fail. If [f] returns [false] on the first character, it will return the empty string. *) val take_while1 : (char -> bool) -> string t (** [take_while1 f] accepts input as long as [f] returns [true] and returns the accepted characters as a string. This parser requires that [f] return [true] for at least one character of input, and will fail otherwise. *) val take_till : (char -> bool) -> string t (** [take_till f] accepts input as long as [f] returns [false] and returns the accepted characters as a string. This parser does not fail. If [f] returns [true] on the first character, it will return the empty string. *) val consumed : _ t -> string t (** [consumed p] runs [p] and returns the contents that were consumed during the parsing as a string *) val take_bigstring : int -> bigstring t (** [take_bigstring n] accepts exactly [n] characters of input and returns them as a newly allocated bigstring. *) val take_bigstring_while : (char -> bool) -> bigstring t (** [take_bigstring_while f] accepts input as long as [f] returns [true] and returns the accepted characters as a newly allocated bigstring. This parser does not fail. If [f] returns [false] on the first character, it will return the empty bigstring. *) val take_bigstring_while1 : (char -> bool) -> bigstring t (** [take_bigstring_while1 f] accepts input as long as [f] returns [true] and returns the accepted characters as a newly allocated bigstring. This parser requires that [f] return [true] for at least one character of input, and will fail otherwise. *) val take_bigstring_till : (char -> bool) -> bigstring t (** [take_bigstring_till f] accepts input as long as [f] returns [false] and returns the accepted characters as a newly allocated bigstring. This parser does not fail. If [f] returns [true] on the first character, it will return the empty bigstring. *) val consumed_bigstring : _ t -> bigstring t (** [consumed p] runs [p] and returns the contents that were consumed during the parsing as a bigstring *) val advance : int -> unit t (** [advance n] advances the input [n] characters, failing if the remaining input is less than [n]. *) val end_of_line : unit t (** [end_of_line] accepts either a line feed [\n], or a carriage return followed by a line feed [\r\n] and returns unit. *) val at_end_of_input : bool t (** [at_end_of_input] returns whether the end of the end of input has been reached. This parser always succeeds. *) val end_of_input : unit t (** [end_of_input] succeeds if all the input has been consumed, and fails otherwise. *) val scan : 'state -> ('state -> char -> 'state option) -> (string * 'state) t (** [scan init f] consumes until [f] returns [None]. Returns the final state before [None] and the accumulated string *) val scan_state : 'state -> ('state -> char -> 'state option) -> 'state t (** [scan_state init f] is like {!scan} but only returns the final state before [None]. Much more efficient than {!scan}. *) val scan_string : 'state -> ('state -> char -> 'state option) -> string t (** [scan_string init f] is like {!scan} but discards the final state and returns the accumulated string. *) val int8 : int -> int t (** [int8 i] accepts one byte that matches the lower-order byte of [i] and returns unit. *) val any_uint8 : int t (** [any_uint8] accepts any byte and returns it as an unsigned int8. *) val any_int8 : int t (** [any_int8] accepts any byte and returns it as a signed int8. *) (** Big endian parsers *) module BE : sig val int16 : int -> unit t (** [int16 i] accept two bytes that match the two lower order bytes of [i] and returns unit. *) val int32 : int32 -> unit t (** [int32 i] accept four bytes that match the four bytes of [i] and returns unit. *) val int64 : int64 -> unit t (** [int64 i] accept eight bytes that match the eight bytes of [i] and returns unit. *) val any_int16 : int t val any_int32 : int32 t val any_int64 : int64 t (** [any_intN] reads [N] bits and interprets them as big endian signed integers. *) val any_uint16 : int t (** [any_uint16] reads [16] bits and interprets them as a big endian unsigned integer. *) val any_float : float t (** [any_float] reads 32 bits and interprets them as a big endian floating point value. *) val any_double : float t (** [any_double] reads 64 bits and interprets them as a big endian floating point value. *) end (** Little endian parsers *) module LE : sig val int16 : int -> unit t (** [int16 i] accept two bytes that match the two lower order bytes of [i] and returns unit. *) val int32 : int32 -> unit t (** [int32 i] accept four bytes that match the four bytes of [i] and returns unit. *) val int64 : int64 -> unit t (** [int32 i] accept eight bytes that match the eight bytes of [i] and returns unit. *) val any_int16 : int t val any_int32 : int32 t val any_int64 : int64 t (** [any_intN] reads [N] bits and interprets them as little endian signed integers. *) val any_uint16 : int t (** [uint16] reads [16] bits and interprets them as a little endian unsigned integer. *) val any_float : float t (** [any_float] reads 32 bits and interprets them as a little endian floating point value. *) val any_double : float t (** [any_double] reads 64 bits and interprets them as a little endian floating point value. *) end (** {2 Combinators} *) val option : 'a -> 'a t -> 'a t (** [option v p] runs [p], returning the result of [p] if it succeeds and [v] if it fails. *) val both : 'a t -> 'b t -> ('a * 'b) t (** [both p q] runs [p] followed by [q] and returns both results in a tuple *) val list : 'a t list -> 'a list t (** [list ps] runs each [p] in [ps] in sequence, returning a list of results of each [p]. *) val count : int -> 'a t -> 'a list t (** [count n p] runs [p] [n] times, returning a list of the results. *) val many : 'a t -> 'a list t (** [many p] runs [p] {i zero} or more times and returns a list of results from the runs of [p]. *) val many1 : 'a t -> 'a list t (** [many1 p] runs [p] {i one} or more times and returns a list of results from the runs of [p]. *) val many_till : 'a t -> _ t -> 'a list t (** [many_till p e] runs parser [p] {i zero} or more times until action [e] succeeds and returns the list of result from the runs of [p]. *) val sep_by : _ t -> 'a t -> 'a list t (** [sep_by s p] runs [p] {i zero} or more times, interspersing runs of [s] in between. *) val sep_by1 : _ t -> 'a t -> 'a list t (** [sep_by1 s p] runs [p] {i one} or more times, interspersing runs of [s] in between. *) val skip_many : _ t -> unit t (** [skip_many p] runs [p] {i zero} or more times, discarding the results. *) val skip_many1 : _ t -> unit t (** [skip_many1 p] runs [p] {i one} or more times, discarding the results. *) val fix : ('a t -> 'a t) -> 'a t (** [fix f] computes the fixpoint of [f] and runs the resultant parser. The argument that [f] receives is the result of [fix f], which [f] must use, paradoxically, to define [fix f]. [fix] is useful when constructing parsers for inductively-defined types such as sequences, trees, etc. Consider for example the implementation of the {!many} combinator defined in this library: {[let many p = fix (fun m -> (cons <$> p <*> m) <|> return [])]} [many p] is a parser that will run [p] zero or more times, accumulating the result of every run into a list, returning the result. It's defined by passing [fix] a function. This function assumes its argument [m] is a parser that behaves exactly like [many p]. You can see this in the expression comprising the left hand side of the alternative operator [<|>]. This expression runs the parser [p] followed by the parser [m], and after which the result of [p] is cons'd onto the list that [m] produces. The right-hand side of the alternative operator provides a base case for the combinator: if [p] fails and the parse cannot proceed, return an empty list. Another way to illustrate the uses of [fix] is to construct a JSON parser. Assuming that parsers exist for the basic types such as [false], [true], [null], strings, and numbers, the question then becomes how to define a parser for objects and arrays? Both contain values that are themselves JSON values, so it seems as though it's impossible to write a parser that will accept JSON objects and arrays before writing a parser for JSON values as a whole. This is the exact situation that [fix] was made for. By defining the parsers for arrays and objects within the function that you pass to [fix], you will gain access to a parser that you can use to parse JSON values, the very parser you are defining! {[let json = fix (fun json -> let arr = char '[' *> sep_by (char ',') json <* char ']' in let obj = char '{' *> ... json ... <* char '}' in choice [str; num; arr json, ...])]} *) (** [fix_lazy] is like [fix], but after the function reaches [max_steps] deep, it wraps up the remaining computation and yields back to the root of the parsing loop where it continues from there. This is an effective way to break up the stack trace into more managable chunks, which is important for Js_of_ocaml due to the lack of tailrec optimizations for CPS-style tail calls. When compiling for Js_of_ocaml, [fix] itself is defined as [fix_lazy ~max_steps:20]. *) val fix_lazy : max_steps:int -> ('a t -> 'a t) -> 'a t (** {2 Alternatives} *) val (<|>) : 'a t -> 'a t -> 'a t (** [p <|> q] runs [p] and returns the result if succeeds. If [p] fails, then the input will be reset and [q] will run instead. *) val choice : ?failure_msg:string -> 'a t list -> 'a t (** [choice ?failure_msg ts] runs each parser in [ts] in order until one succeeds and returns that result. In the case that none of the parser succeeds, then the parser will fail with the message [failure_msg], if provided, or a much less informative message otherwise. *) val () : 'a t -> string -> 'a t (** [p name] associates [name] with the parser [p], which will be reported in the case of failure. *) val commit : unit t (** [commit] prevents backtracking beyond the current position of the input, allowing the manager of the input buffer to reuse the preceding bytes for other purposes. The {!module:Unbuffered} parsing interface will report directly to the caller the number of bytes committed to the when returning a {!Unbuffered.state.Partial} state, allowing the caller to reuse those bytes for any purpose. The {!module:Buffered} will keep track of the region of committed bytes in its internal buffer and reuse that region to store additional input when necessary. *) (** {2 Monadic/Applicative interface} *) val return : 'a -> 'a t (** [return v] creates a parser that will always succeed and return [v] *) val fail : string -> _ t (** [fail msg] creates a parser that will always fail with the message [msg] *) val (>>=) : 'a t -> ('a -> 'b t) -> 'b t (** [p >>= f] creates a parser that will run [p], pass its result to [f], run the parser that [f] produces, and return its result. *) val bind : 'a t -> f:('a -> 'b t) -> 'b t (** [bind] is a prefix version of [>>=] *) val (>>|) : 'a t -> ('a -> 'b) -> 'b t (** [p >>| f] creates a parser that will run [p], and if it succeeds with result [v], will return [f v] *) val (<*>) : ('a -> 'b) t -> 'a t -> 'b t (** [f <*> p] is equivalent to [f >>= fun f -> p >>| f]. *) val (<$>) : ('a -> 'b) -> 'a t -> 'b t (** [f <$> p] is equivalent to [p >>| f] *) val ( *>) : _ t -> 'a t -> 'a t (** [p *> q] runs [p], discards its result and then runs [q], and returns its result. *) val (<* ) : 'a t -> _ t -> 'a t (** [p <* q] runs [p], then runs [q], discards its result, and returns the result of [p]. *) val lift : ('a -> 'b) -> 'a t -> 'b t val lift2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t val lift3 : ('a -> 'b -> 'c -> 'd) -> 'a t -> 'b t -> 'c t -> 'd t val lift4 : ('a -> 'b -> 'c -> 'd -> 'e) -> 'a t -> 'b t -> 'c t -> 'd t -> 'e t (** The [liftn] family of functions promote functions to the parser monad. For any of these functions, the following equivalence holds: {[liftn f p1 ... pn = f <$> p1 <*> ... <*> pn]} These functions are more efficient than using the applicative interface directly, mostly in terms of memory allocation but also in terms of speed. Prefer them over the applicative interface, even when the arity of the function to be lifted exceeds the maximum [n] for which there is an implementation for [liftn]. In other words, if [f] has an arity of [5] but only [lift4] is provided, do the following: {[lift4 f m1 m2 m3 m4 <*> m5]} Even with the partial application, it will be more efficient than the applicative implementation. *) val map : 'a t -> f:('a -> 'b) -> 'b t val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t val map3 : 'a t -> 'b t -> 'c t -> f:('a -> 'b -> 'c -> 'd) -> 'd t val map4 : 'a t -> 'b t -> 'c t -> 'd t -> f:('a -> 'b -> 'c -> 'd -> 'e) -> 'e t (** The [mapn] family of functions are just like [liftn], with a slightly different interface. *) (** The [Let_syntax] module is intended to be used with the [ppx_let] pre-processor, and just contains copies of functions described elsewhere. *) module Let_syntax : sig val return : 'a -> 'a t val ( >>| ) : 'a t -> ('a -> 'b) -> 'b t val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t module Let_syntax : sig val return : 'a -> 'a t val map : 'a t -> f:('a -> 'b) -> 'b t val bind : 'a t -> f:('a -> 'b t) -> 'b t val both : 'a t -> 'b t -> ('a * 'b) t val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t val map3 : 'a t -> 'b t -> 'c t -> f:('a -> 'b -> 'c -> 'd) -> 'd t val map4 : 'a t -> 'b t -> 'c t -> 'd t -> f:('a -> 'b -> 'c -> 'd -> 'e) -> 'e t end end val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t (** Unsafe Operations on Angstrom's Internal Buffer These functions are considered {b unsafe} as they expose the input buffer to client code without any protections against modification, or leaking references. They are exposed to support performance-sensitive parsers that want to avoid allocation at all costs. Client code should take care to write the input buffer callback functions such that they: {ul {- do not modify the input buffer {i outside} of the range [\[off, off + len)];} {- do not modify the input buffer {i inside} of the range [\[off, off + len)] if the parser might backtrack; and} {- do not return any direct or indirect references to the input buffer.}} If the input buffer callback functions do not do any of these things, then the client may consider their use safe. *) module Unsafe : sig val take : int -> (bigstring -> off:int -> len:int -> 'a) -> 'a t (** [take n f] accepts exactly [n] characters of input into the parser's internal buffer then calls [f buffer ~off ~len]. [buffer] is the parser's internal buffer. [off] is the offset from the start of [buffer] containing the requested content. [len] is the length of the requested content. [len] is guaranteed to be equal to [n]. *) val take_while : (char -> bool) -> (bigstring -> off:int -> len:int -> 'a) -> 'a t (** [take_while check f] accepts input into the parser's interal buffer as long as [check] returns [true] then calls [f buffer ~off ~len]. [buffer] is the parser's internal buffer. [off] is the offset from the start of [buffer] containing the requested content. [len] is the length of the content matched by [check]. This parser does not fail. If [check] returns [false] on the first character, [len] will be [0]. *) val take_while1 : (char -> bool) -> (bigstring -> off:int -> len:int -> 'a) -> 'a t (** [take_while1 check f] accepts input into the parser's interal buffer as long as [check] returns [true] then calls [f buffer ~off ~len]. [buffer] is the parser's internal buffer. [off] is the offset from the start of [buffer] containing the requested content. [len] is the length of the content matched by [check]. This parser requires that [f] return [true] for at least one character of input, and will fail otherwise. *) val take_till : (char -> bool) -> (bigstring -> off:int -> len:int -> 'a) -> 'a t (** [take_till check f] accepts input into the parser's interal buffer as long as [check] returns [false] then calls [f buffer ~off ~len]. [buffer] is the parser's internal buffer. [off] is the offset from the start of [buffer] containing the requested content. [len] is the length of the content matched by [check]. This parser does not fail. If [check] returns [true] on the first character, [len] will be [0]. *) val peek : int -> (bigstring -> off:int -> len:int -> 'a) -> 'a t (** [peek n ~f] accepts exactly [n] characters and calls [f buffer ~off ~len] with [len = n]. If there is not enough input, it will fail. This parser does not advance the input. Use it for lookahead. *) end (** {2 Running} *) module Consume : sig type t = | Prefix | All end val parse_bigstring : consume:Consume.t -> 'a t -> bigstring -> ('a, string) result (** [parse_bigstring ~consume t bs] runs [t] on [bs]. The parser will receive an [`Eof] after all of [bs] has been consumed. Passing {!Prefix} in the [consume] argument allows the parse to successfully complete without reaching eof. To require the parser to reach eof, pass {!All} in the [consume] argument. For use-cases requiring that the parser be fed input incrementally, see the {!module:Buffered} and {!module:Unbuffered} modules below. *) val parse_string : consume:Consume.t -> 'a t -> string -> ('a, string) result (** [parse_string ~consume t bs] runs [t] on [bs]. The parser will receive an [`Eof] after all of [bs] has been consumed. Passing {!Prefix} in the [consume] argument allows the parse to successfully complete without reaching eof. To require the parser to reach eof, pass {!All} in the [consume] argument. For use-cases requiring that the parser be fed input incrementally, see the {!module:Buffered} and {!module:Unbuffered} modules below. *) (** Buffered parsing interface. Parsers run through this module perform internal buffering of input. The parser state will keep track of unconsumed input and attempt to minimize memory allocation and copying. The {!Buffered.state.Partial} parser state will accept newly-read, incremental input and copy it into the internal buffer. Users can feed parser states using the {!feed} function. As a result, the interface is much easier to use than the one exposed by the {!Unbuffered} module. On success or failure, any unconsumed input will be returned to the user for additional processing. The buffer that the unconsumed input is returned in can also be reused. *) module Buffered : sig type unconsumed = { buf : bigstring ; off : int ; len : int } type input = [ `Bigstring of bigstring | `String of string ] type 'a state = | Partial of ([ input | `Eof ] -> 'a state) (** The parser requires more input. *) | Done of unconsumed * 'a (** The parser succeeded. *) | Fail of unconsumed * string list * string (** The parser failed. *) val parse : ?initial_buffer_size:int -> 'a t -> 'a state (** [parse ?initial_buffer_size t] runs [t] and awaits input if needed. [parse] will allocate a buffer of size [initial_buffer_size] (defaulting to 4k bytes) to do input buffering and automatically grows the buffer as needed. *) val feed : 'a state -> [ input | `Eof ] -> 'a state (** [feed state input] supplies the parser state with more input. If [state] is [Partial], then parsing will continue where it left off. Otherwise, the parser is in a [Fail] or [Done] state, in which case the [input] will be copied into the state's buffer for later use by the caller. *) val state_to_option : 'a state -> 'a option (** [state_to_option state] returns [Some v] if the parser is in the [Done (bs, v)] state and [None] otherwise. This function has no effect on the current state of the parser. *) val state_to_result : 'a state -> ('a, string) result (** [state_to_result state] returns [Ok v] if the parser is in the [Done (bs, v)] state and [Error msg] if it is in the [Fail] or [Partial] state. This function has no effect on the current state of the parser. *) val state_to_unconsumed : _ state -> unconsumed option (** [state_to_unconsumed state] returns [Some bs] if [state = Done(bs, _)] or [state = Fail(bs, _, _)] and [None] otherwise. *) end (** Unbuffered parsing interface. Use this module for total control over memory allocation and copying. Parsers run through this module perform no internal buffering. Instead, the user is responsible for managing a buffer containing the entirety of the input that has yet to be consumed by the parser. The {!Unbuffered.state.Partial} parser state reports to the user how much input the parser consumed during its last run, via the {!Unbuffered.partial.committed} field. This area of input must be discarded before parsing can resume. Once additional input has been collected, the unconsumed input as well as new input must be passed to the parser state via the {!Unbuffered.partial.continue} function, together with an indication of whether there is {!Unbuffered.more} input to come. The logic that must be implemented in order to make proper use of this module is intricate and tied to your OS environment. It's advisable to use the {!Buffered} module when initially developing and testing your parsers. For production use-cases, consider the Async and Lwt support that this library includes before attempting to use this module directly. *) module Unbuffered : sig type more = | Complete | Incomplete type 'a state = | Partial of 'a partial (** The parser requires more input. *) | Done of int * 'a (** The parser succeeded, consuming specified bytes. *) | Fail of int * string list * string (** The parser failed, consuming specified bytes. *) and 'a partial = { committed : int (** The number of bytes committed during the last input feeding. Callers must drop this number of bytes from the beginning of the input on subsequent calls. See {!commit} for additional details. *) ; continue : bigstring -> off:int -> len:int -> more -> 'a state (** A continuation of a parse that requires additional input. The input should include all uncommitted input (as reported by previous partial states) in addition to any new input that has become available, as well as an indication of whether there is {!more} input to come. *) } val parse : 'a t -> 'a state (** [parse t] runs [t] and await input if needed. *) val state_to_option : 'a state -> 'a option (** [state_to_option state] returns [Some v] if the parser is in the [Done (bs, v)] state and [None] otherwise. This function has no effect on the current state of the parser. *) val state_to_result : 'a state -> ('a, string) result (** [state_to_result state] returns [Ok v] if the parser is in the [Done (bs, v)] state and [Error msg] if it is in the [Fail] or [Partial] state. This function has no effect on the current state of the parser. *) end (** {2 Expert Parsers} For people that know what they're doing. If you want to use them, read the code. No further documentation will be provided. *) val pos : int t val available : int t