diff --git a/sexpr.ml b/sexpr.ml index 65d4423..62381aa 100644 --- a/sexpr.ml +++ b/sexpr.ml @@ -224,10 +224,11 @@ type 'a state = | Bottom : 'a state | Push : ('b parser * ('b -> 'a state)) -> 'a state -(** Actually parse the sequence of tokens *) -let parse p tokens = - let res = ref None in - let state = Push(p, fun x -> (res := Some x; Bottom)) in +(** Actually parse the sequence of tokens, with a callback to be called + on every parsed value. The callback decides whether to push another + state or whether to continue. *) +let parse_k p tokens k = + let rec state = Push(p, fun x -> match k x with `Stop -> Bottom | `Continue -> state) in (* Token handler. It also takes the current parser. *) let rec one_step state token = match state with @@ -255,9 +256,21 @@ let parse p tokens = | Push (Fail reason, _) -> raise (ParseFailure reason) in (* iterate on the tokens *) - ignore (Sequence.fold one_step state tokens); + ignore (Sequence.fold one_step state tokens) + +(** Parse one value *) +let parse p tokens = + let res = ref None in + parse_k p tokens (fun x -> res := Some x; `Stop); (* return result *) match !res with | None -> raise (ParseFailure "incomplete input") | Some x -> x +(** Parse a sequence of values *) +let parse_seq p tokens = + let seq_fun k = + parse_k p tokens (fun x -> k x; `Continue) + in + Sequence.from_iter seq_fun + diff --git a/sexpr.mli b/sexpr.mli index b0171e6..e3ca05a 100644 --- a/sexpr.mli +++ b/sexpr.mli @@ -110,5 +110,8 @@ val many : 'a parser -> 'a list parser val many1 : 'a parser -> 'a list parser val parse : 'a parser -> token Sequence.t -> 'a - (** Actually parse the sequence of tokens. Raises + (** Parses exactly one value from the sequence of tokens. Raises ParseFailure if anything goes wrong. *) + +val parse_seq : 'a parser -> token Sequence.t -> 'a Sequence.t + (** Parses a sequence of values *)