reparse-lwt

Reparse Lwt_stream.t input support
IN THIS PACKAGE
Module Reparse_lwt . Stream
include Reparse.PARSER with type 'a promise = 'a Lwt.t
type 'a t

Represents a parser which can parse value 'a. Use parse functions to evaluate a parser.

type 'a promise = 'a Lwt.t
type input
type pos = int
val parse : ?pos:pos -> input -> 'a t -> ( 'a * pos, string ) result promise

parse ?pos input p parses input using parser p from given pos. It returns a tuple 'a * pos which represents a parsed value 'a and the final parser position pos.

Default value for pos is 0.

Monadic operators

val return : 'a -> 'a t

return v always parses value v.

Examples

module P = Reparse.String.String;;

let input = new P.string_input "" in
let v1 = P.(parse input (return 5)) in
let v2 = P.(parse input (return "hello")) in
v1 = 5 && v2 = "hello"
val unit : unit t

unit always parses to ():unit value.

val ignore : _ t -> unit t

ignore p ignore any result from p upon success and return () instead.

val fail : string -> 'a t

fail err_msg returns a parser that always fails with err_msg.

Examples

module P = Reparse.String;;

let input = new P.string_input "" in
let r =
  try
    let _ = P.(parse input (fail "hello error")) in
    assert false
  with e -> e
in
r
= P.Parser
    {offset= 0; line_number= 0; column_number= 0; msg= "hello error"}
val bind : ( 'a -> 'b t ) -> 'a t -> 'b t

bind f p is prefix version of p >>= f.

val both : 'a t -> 'b t -> ('a * 'b) t

both p q is evaluates to (a,b) when a is evaluted from p and b is evaluated from q.

val apply : ( 'a -> 'b ) t -> 'a t -> 'b t
val map : ( 'a -> 'b ) -> 'a t -> 'b t

map f p is prefix version of p >>| f.

val map2 : ( 'a -> 'b -> 'c ) -> 'a t -> 'b t -> 'c t
val map3 : ( 'a -> 'b -> 'c -> 'd ) -> 'a t -> 'b t -> 'c t -> 'd t
val map4 : ( 'a -> 'b -> 'c -> 'd -> 'e ) -> 'a t -> 'b t -> 'c t -> 'd t -> 'e t
module Infix : sig ... end
include module type of Infix
val (>>=) : 'a t -> ( 'a -> 'b t ) -> 'b t

p >>= f returns a new parser b where,

  • a is the parsed value of p
  • b is f a Also known as bind operation.

Examples

module P = Reparse.String
open P;;

let f a = P.pure (Char.code a) in
let p = P.char 'h' in
let p = p >>= f in
let v = P.parse_string p "hello" in
v = 104
val (>>|) : 'a t -> ( 'a -> 'b ) -> 'b t

p >>| f returns a new parser encapsulating value b where,

  • a is the parsed value of p.
  • b is f a. Also known as map operation.

Examples

module P = Reparse.String
open P;;

let f a = Char.code a in
let p = P.char 'h' in
let p = p >>| f in
let v = P.parse_string p "hello" in
v = 104
val (<*>) : 'a t -> ( 'a -> 'b ) t -> 'b t

pf <*> q returns a new parser encapsulating value b where

  • pf and q are evaluated sequentially in order as given.
  • f is the parsed value of pf
  • a is the parsed value of q
  • b is f a Also known as Applicative operation.

Examples

module P = Reparse
open P;;

let f a = a + 2 in
let pf = P.pure f in
let q = P.pure 2 in
let p = pf <*> q in
let v = P.parse_string p "hello" in
v = 4
val (<$>) : 'a t -> ( 'a -> 'b ) -> 'b t

f <$> p is return f <*> p.

val (<$$>) : ('a t * 'b t) -> ( 'a -> 'b -> 'c ) -> 'c t
val (<$$$>) : ('a t * 'b t * 'c t) -> ( 'a -> 'b -> 'c -> 'd ) -> 'd t
val (<$$$$>) : ('a t * 'b t * 'c t * 'd t) -> ( 'a -> 'b -> 'c -> 'd -> 'e ) -> 'e t
val (<$) : 'a -> 'b t -> 'a t

v <$ p replaces the parse value of p with v.

Examples

module P = Reparse.String
open P;;

let v = "hello" in
let p = P.char 'h' in
let p = v <$ p in
let v2 = P.parse_string p "hello" in
v2 = "hello"
val ($>) : 'a t -> 'b -> 'b t

p $> v is inverse of v <$ p.

val (*>) : _ t -> 'b t -> 'b t

p *> q returns a parser encapsulating value a where,

  • p, q are evaluated sequentially in order as given.
  • a is parsed value of q.
  • The parsed value of p is discarded. Also known as discard left.

Examples

module P = Reparse.String
open P;;

let p = P.string "world" in
let q = P.pure "hello" in
let p = p *> q in
let v = P.parse_string p "world" in
v = "hello"
val (<*) : 'a t -> _ t -> 'a t

p <* q returns a parser encapsulating value a where,

  • p, q are evaluated sequentially in order as given.
  • a is parsed value of p.
  • The parsed value of q is discarded. Also know as discard_right.

Examples

module P = Reparse.String
open P;;

let p = P.string "world" in
let q = P.pure "hello" in
let p = p <* q in
let v = P.parse_string p "world" in
v = "world"
val (<|>) : 'a t -> 'a t -> 'a t

p <|> q returns a parser encapsulating value a where,

  • p,q are evaluated sequentially in order as given.
  • a is the parsed value of p if p is successful
  • a is the parsed value of q if p is a failure and q is a success.
  • If both - p and q - fails, then the parser fails.

Examples

p fails and q succeeds, therefore we return q's parsed value 'w'

module P = Reparse.String
open P;;

let p = P.char 'h' in
let q = P.char 'w' in
let p = p <|> q in
let v = P.parse_string p "world" in
v = 'w'

p succeeds therefore we return its parsed value 'h'

let p = P.char 'h' in
let q = P.char 'w' in
let p = p <|> q in
let v = P.parse_string p "hello" in
v = 'h'

The parser fails if both p and q fails.

let p = P.char 'h' in
let q = P.char 'w' in
let p = p <|> q in
let v =
  try
    let _ = P.parse_string p "" in
    false
  with _ -> true
in
v = true
val let* : 'a t -> ( 'a -> 'b t ) -> 'b t

let* is a let syntax binding for Reparse.Infix.((>>=))

Examples

module P = Reparse.String
open P;;

let p =
  let* a = P.pure 5 in
  let total = a + 5 in
  P.pure total
in
let v = P.parse_string p "" in
v = 10
val and* : 'a t -> 'b t -> ('a * 'b) t
val let+ : 'a t -> ( 'a -> 'b ) -> 'b t

let* is a let syntax binding for Reparse.((>|=))

Examples

module P = Reparse.String
open P;;

let p =
  let+ a = P.pure 5 in
  let total = a + 5 in
  total
in
let v = P.parse_string p "" in
v = 10
val and+ : 'a t -> 'b t -> ('a * 'b) t
val (<?>) : 'a t -> string -> 'a t

p <?> err_msg parses p to value a and returns a new parser encapsulating a. If p is a failure, then it fails with error message err_msg. Often used as a last choice in <|>, e.g. a <|> b <|> c <?> "expected a b c".

Examples

module P = Reparse.String
open P;;

let p = P.char 'h' <|> P.char 'w' in
let err_msg = "[error]" in
let p = p <?> err_msg in
let v =
  try
    let _ = P.parse_string p "" in
    false
  with
  | P.Parser
      {offset= 0; line_number= 0; column_number= 0; msg= "[error]"} ->
      true
  | _ -> false
in
v = true
module Let_syntax : sig ... end

ppx_let syntax support module.

module Promise : sig ... end

Char/String parsers

val peek_char : char t

peek_char t parses the next character from input without consuming it. It fails if EOI is reached.

Examples

module P = Reparse.String;;

let p = P.peek_char in
let v = P.parse_string p "hello" in
v = 'h'

Input is not consumed.

val peek_char_opt : char option t

peek_char_opt is the exception safe version of peek_char. It returns an option rather than throwing exn when EOI is reached.

val peek_string : int -> string t

peek_string n parse a string of length n without consuming it.

Examples

module P = Reparse.String
open P;;

let p = P.peek_string 5 in
let v = P.parse_string p "hello" in
v = "hello"

Input is not consumed.

val any_char : char t

any_char parses the next character from input. Fails if input has reached end of input.

Examples

module P = Reparse.String;;

let v = P.(parse_string any_char "hello") in
v = 'h'
val unsafe_any_char : char t

unsafe_any_char is same as any_char except the returned char value is not buffered by the input. Important don't use this parser with backtracking parsers such as <|>, alt, any etc.

Note Ensure you call trim_input_buffer after calling this parser.

val char : char -> char t

char c parses character c exactly.

Examples

module P = Reparse.String;;

let p = P.char 'h' in
let v = P.parse_string p "hello" in
v = 'h'
val char_if : ( char -> bool ) -> char t

char_if f parses a character c if f c is true.

Examples

module P = Reparse.String;;

let p = P.char_if (function 'a' -> true | _ -> false) in
let v = P.parse_string p "abc" in
v = 'a'
val string_cs : string -> string t

string_cs s parses a string s exactly. String comparison is case sensitive.

Examples

module P = Reparse.String;;

let p = P.string_cs "hello" in
let v = P.parse p (P.of_string "hello world") in
v = "hello"
val string_ci : string -> string t
val string_of_chars : char list -> string t

string_of_chars l converts char list l to string

Examples

module P = Reparse.String;;

let p = P.(take ~sep_by:space next >>= string_of_chars) in
let v = P.parse_string p "h e l l o" in
v = "hello"
val take_string : int -> string t

take_string n returns a string of length n exactly from input.

val take_cstruct : int -> Cstruct.t t

take_cstruct n returns a Cstruct.t of length n exactly from input. This is usually a zero copy if input is an unbuffered input type.

val unsafe_take_cstruct : int -> Cstruct.t t

unsafe_take_cstruct n reads n bytes exactly from input without buffering. Since the read n bytes is unbuffered, the parser is unable to backtrack beyond position pos + n where pos is the input position before the parser is called.

Note: Ensure that unsafe_take_cstruct is not being run as part of combinators that require backtracking such as <|>, any. Additionally it is recommended to call trim_input_buffer after calling unsafe_take_cstruct.

val unsafe_take_cstruct_ne : int -> Cstruct.t t

unsafe_take_cstruct_ne n is same as unsafe_take_cstruct n except that n represents the maximum number of bytes read.

Alternate parsers

val any : ?failure_msg:string -> 'a t list -> 'a t

any l parses the value of the first successful parser in list l. Specified parsers in l are evaluated sequentially from left to right. A failed parser doesn't consume any input, i.e. offset is unaffected. The parser fails if none of the parsers in l are evaluated successfully.

Examples

First successful parser result is returned

module P = Reparse.String;;

let p = P.(any [char 'z'; char 'x'; char 'a']) in
let v = P.parse_string p "zabc" in
v = 'z'
;;

let p = P.(any [char 'z'; char 'x'; char 'a']) in
let v = P.parse_string p "xabc" in
v = 'x'
;;

let p = P.(any [char 'z'; char 'x'; char 'a']) in
let v = P.parse_string p "abc" in
v = 'a'

Parser fails when none of the parsers in l are successful.

let p = P.(any [char 'z'; char 'x'; char 'a']) in
let v =
  try
    let _ = P.parse_string p "yyy" in
    false
  with _ -> true
in
v = true
val alt : 'a t -> 'a t -> 'a t

alt p q is p <|> q. See Reparse.Infix.((<|>))

val optional : 'a t -> 'a option t

optional p parses Some a if successful and None otherwise. a is the parsed value of p.

Examples

module P = Reparse.String
open P;;

let p = P.(optional (char 'a')) in
let v = P.parse_string p "ab" in
v = Some 'a'
;;

let p = P.(optional (char 'z')) in
let v = P.parse_string p "ab" in
v = None

Boolean

val not_ : 'a t -> unit t

not_ p parses value () if and only if p fails to parse, otherwise the parse fails.

Examples

module P = Reparse.String;;

let p = P.(not_ (char 'a')) in
let v = P.parse_string p "bbb" in
v = ()
val is : 'a t -> bool t

is p parses true if p is successful, false otherwise. Note evaluation of p doesn't consume any input.

Examples

module P = Reparse.String;;

let p = P.(is (char 'b')) in
let v = P.parse_string p "bcb" in
v = true
val is_not : 'a t -> bool t

is_not p parses value true if p fails to parse and false otherwise. Note evaluating p doesn't consume any input.

Examples

module P = Reparse.String;;

let p = P.(is_not (char 'a')) in
let v = P.parse_string p "bbb" in
v = true

Repetition

val recur : ( 'a t -> 'a t ) -> 'a t

recur f returns a recursive parser. Function value f accepts a parser p as its argument and returns a parser q. Parser q in its definition can refer to p and p can refer to q in its own definition. Such parsers are also known as a fixpoint or y combinator.

val all : 'a t list -> 'a list t

all parsers parses all parsers in parsers and returns a list of successful parse result. All of the parsers must succeed for all to succeed.

val all_unit : _ t list -> unit t

all_unit parsers parses parsers and discards their results. All of the parsers must succeed for all_unit to succeed.

val skip : ?at_least:int -> ?up_to:int -> _ t -> int t

skip ~at_least ~up_to p repeatedly parses p and discards its value. The lower and upper bound of repetition is specified by arguments at_least and up_to respectively. The default value of at_least is 0. The default value of up_to is unspecified, i.e. there is no upper limit. The repetition ends when one of the following occurs:

  • p evaluates to failure
  • up_to upper bound value is reached The parser encapsulates the count of times p was evaluated successfully.

Examples

module P = Reparse.String;;

let p = P.(skip space) in
let v = P.parse_string p "     " in
v = 5
val take : ?at_least:int -> ?up_to:int -> ?sep_by:_ t -> 'a t -> 'a list t

take ~at_least ~up_to ~sep_by p repeatedly parses p and returns the parsed values. The lower and upper bound of repetition is specified by arguments at_least and up_to respectively. The default value of at_least is 0. The default value of up_to is unspecified, i.e. there is no upper limit. If sep_by is specified then the evaluation of p must be followed by a successful evaluation of sep_by. The parsed value of sep_by is discarded. The repetition ends when one of the following occurs:

  • p evaluates to failure
  • sep_by evaluates to failure
  • up_to upper boudn value is reached The parser fails if the count of repetition of p does not match the value specified by at_least.

Examples

Default behaviour.

module P = Reparse.String;;

let p = P.(take (char 'a')) in
let v = P.parse_string p "aaaaa" in
v = ['a'; 'a'; 'a'; 'a'; 'a']

Specify ~sep_by.

module P = Reparse.String;;

let p = P.(take ~sep_by:(char ',') (char 'a')) in
let v = P.parse_string p "a,a,a,a,a" in
v = ['a'; 'a'; 'a'; 'a'; 'a']

Specify lower bound argument at_least.

module P = Reparse.String;;

let p = P.(take ~at_least:3 ~sep_by:(char ',') (char 'a')) in
let v = P.parse_string p "a,a,a,a,a" in
v = ['a'; 'a'; 'a'; 'a'; 'a']

Lower bound not met results in error.

module P = Reparse.String;;

let p = P.(take ~at_least:5 ~sep_by:(char ',') (char 'a')) in
let v =
  try
    let _ = P.parse_string p "a,a,a,a" in
    false
  with _ -> true
in
v = true

Specify upper bound up_to.

module P = Reparse.String;;

let p = P.(take ~up_to:3 ~sep_by:(char ',') (char 'a')) in
let v = P.parse_string p "a,a,a,a,a" in
v = ['a'; 'a'; 'a']
val take_while_cb : ?sep_by:_ t -> while_:bool t -> on_take_cb:( 'a -> unit t ) -> 'a t -> unit t

take_while_cb ~sep_by ~while_ ~on_take p repeatedly parses p and calls callback on_take_cb with the parsed value. p is evaluated if and only if while_ evaluates to true. If sep_by is specified then the evaluation of p must be followed by a successful evaluation of sep_by. The parsed value of sep_by is discarded. p is evaluated repeatedly. The repetition ends when one of the following occurs: on_take_cb is the callback function that is called every time p is evaluated.

  • p evaluates to failure
  • while_ returns false
  • sep_by evaluates to failure take_while_cb is the general version of Reparse.take_while. It allows to specify how the value a is to be collected. Note while_ does not consume input.

Examples

module P = Reparse.String
open P;;

let buf = Buffer.create 0 in
let on_take_cb a = Buffer.add_char buf a in
let p =
  P.(take_while_cb (char 'a') ~while_:(is_not (char 'b')) ~on_take_cb)
in
let v = P.parse_string p "aaab" in
let s = Buffer.contents buf in
v = 3 && s = "aaa"
val take_while : ?sep_by:_ t -> while_:bool t -> 'a t -> 'a list t

take_while ~sep_by p ~while_ p repeatedly parses p and returns its value. p is evaluated if and only if while_ evaluates to true. If sep_by is specified then the evaluation of p must be followed by a successful evaluation of sep_by. The parsed value of sep_by is discarded. The repetition ends when one of the following occurs:

  • p evaluates to failure
  • while_ returns false
  • sep_by evaluates to failure Note while_ does not consume input.

Examples

Default behaviour.

module P = Reparse.String;;

let p = P.(take_while ~while_:(is_not (char 'b')) (char 'a')) in
let v = P.parse_string p "aab" in
v = ['a'; 'a']

Specify sep_by.

module P = Reparse.String;;

let p =
  P.(
    take_while ~sep_by:(char ',') ~while_:(is_not (char 'b')) (char 'a'))
in
let v = P.parse_string p "a,a,ab" in
v = ['a'; 'a'; 'a']
val take_between : ?sep_by:_ t -> start:_ t -> end_:_ t -> 'a t -> 'a list t

take_between ~sep_by ~start ~end_ p parses start and then repeatedly parses p while the parsed value of p doesn't equal to parsed value of end_. After the repetition end, it parses end_. The parser returns the list of parsed values of p. Both start and end_ parser values are discarded. If sep_by is specified then the evaluation of p must be followed by a successful evaluation of sep_by. The parsed value of sep_by is discarded. The repetition ends when one of the following occurs:

  • p evaluates to failure
  • end_ parsed value matches p parsed value
  • sep_by evaluates to failure

Examples

module P = Reparse.String;;

let p =
  P.(
    take_between ~sep_by:(char ',') ~start:(P.char '(') ~end_:(char ')')
      next)
in
let v = P.parse_string p "(a,a,a)" in
v = ['a'; 'a'; 'a']

RFC 5234

Parsers as defined in RFC 5234, Appendix B.1.

val alpha : char t

alpha parses a character in range A- Z or a-z.

Examples

module P = Reparse
open P;;

let p = P.(take alpha) in
let v = P.parse_string p "abcdABCD" in
v = ['a'; 'b'; 'c'; 'd'; 'A'; 'B'; 'C'; 'D']
val alpha_num : char t

alpha_num parses a character in range A-Z or a-z or 0-9.

Examples

module P = Reparse
open P;;

let p = P.(take alpha_num) in
let v = P.parse_string p "ab123ABCD" in
v = ['a'; 'b'; '1'; '2'; '3'; 'A'; 'B'; 'C'; 'D']
val lower_alpha : char t

lower_alpha parses a character in range a-z.

Examples

module P = Reparse
open P;;

let p = P.(take lower_alpha) in
let v = P.parse_string p "abcd" in
v = ['a'; 'b'; 'c'; 'd']
val upper_alpha : char t

upper_alpha parses a character in range A-Z.

Examples

module P = Reparse
open P;;

let p = P.(take upper_alpha) in
let v = P.parse_string p "ABCD" in
v = ['A'; 'B'; 'C'; 'D']
val bit : char t

bit parses a character which is either '0' or '1'.

Examples

module P = Reparse;;

let p = P.(take bit) in
let v = P.parse_string p "0110 ab" in
v = ['0'; '1'; '1'; '0']
val ascii_char : char t

ascii_char parses any US-ASCII character.

Examples

module P = Reparse;;

let p = P.(take ascii_char) in
let v = P.parse_string p "0110 abc '" in
v = ['0'; '1'; '1'; '0'; ' '; 'a'; 'b'; 'c'; ' '; '\'']
val cr : char t

cr parses character '\r'.

Examples

module P = Reparse;;

let v = P.(parse_string cr "\rab") in
v = '\r'
val crlf : string t

crlf parses string "\r\n".

Examples

module P = Reparse;;

let v = P.(parse_string crlf "\r\n abc") in
v = "\r\n"
val control : char t

control parses characters in range 0x00 - 0x1F or character 0x7F.

Examples

module P = Reparse;;

let v = P.(parse_string control "\x00") in
v = '\x00'
val digit : char t

digit parses one of the digit characters, 0 .. 9.

Examples

module P = Reparse;;

let p = P.(take digit) in
let v = P.parse_string p "0123456789a" in
v = ['0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9']
val digits : string t

digits parses one or more digit characters, 0 .. 9.

Examples

module P = Reparse;;

let v = P.(parse_string digits "1234 +") in
v = "1234"
val dquote : char t

dquote parses double quote character '"'.

Examples

module P = Reparse;;

let v = P.(parse_string dquote "\"hello ") in
v = '"'
val hex_digit : char t

hex_digit parses any of the hexadecimal digits - 0..9, A, B, C, D, E, F.

Examples

module P = Reparse;;

let p = P.(take hex_digit) in
let v = P.parse_string p "0ABCDEFa" in
v = ['0'; 'A'; 'B'; 'C'; 'D'; 'E'; 'F']
val htab : char t

htab parses a horizontal tab character '\t'.

Examples

module P = Reparse;;

let v = P.(parse_string htab "\t") in
v = '\t'
val lf : char t

lf parses a linefeed '\n' character.

Examples

module P = Reparse;;

let v = P.(parse_string lf "\n") in
v = '\n'
val octet : char t

octect parses any character in the range \x00 - \xFF. Synonym for Reparse.next

Examples

module P = Reparse;;

let p = P.(take octet) in
let v = P.parse_string p "0110 abc '" in
v = ['0'; '1'; '1'; '0'; ' '; 'a'; 'b'; 'c'; ' '; '\'']
val space : char t

space parses a space character.

Examples

module P = Reparse;;

let v = P.(parse_string space " abc '") in
v = ' '
val vchar : char t

vchar parses any of the visible - printable - characters.

Examples

module P = Reparse;;

let p = P.(take vchar) in
let v = P.parse_string p "0110abc\x00" in
v = ['0'; '1'; '1'; '0'; 'a'; 'b'; 'c']
val whitespace : char t

whitespace parses a space ' ' or horizontal tab '\t' character.

Examples

module P = Reparse;;

let p = P.(take whitespace) in
let v = P.parse_string p "\t \t " in
v = ['\t'; ' '; '\t'; ' ']

Input manipulation

val advance : int -> unit t

advance n advances input by n bytes.

val eoi : unit t

eoi parses end of input. Fails if parser is not at end of input.

Examples

module P = Reparse.String;;

let v = P.(parse_string eoi "") in
v = ()
;;

let v =
  try
    let _ = P.(parse_string eoi "a") in
    false
  with _ -> true
in
v = true
val trim_input_buffer : unit t

trim_input_buffer () calls INPUT.trim_buffer with the current parser position. Use this function to control the memory consumption of the input buffer.

Note Once trimmed the parser is unable to backtrack beyond the position of last_trimmed_pos. This may affect a correct functioning of <|> parser as it backtracks when trying various alternatives.

val pos : int t

pos returns the current parser position.

val last_trimmed_pos : int t

last_trimmed_pos returns the last trimmed input position marker.

val input_buffer_size : int option t

input_buffer_size returns current input buffer size in bytes if input is a buffered input otherwise it returns None for unbuffered input.

val of_promise : 'a promise -> 'a t
val create_input : char Lwt_stream.t -> input