Source

ocaml-indent / filter.ml

The default branch has multiple heads

open Sexplib.Conv
open Pos
open Reader
open Parser

type 'a t = 
  | Cons of 'a * 'a t lazy_t * in_channel
  | Null

type 'a info = {
  space : string;
  token : 'a;
  region : Region.t;
  substr : string;
}

let streamer path = 
  let ic = open_in path in
  try
    let reader = LexReader.create_from_channel ic in
    let rec loop last_region = 
      let token = LexReader.lex reader Lexer.token in
      let region = LexReader.region reader in
      let space_between = 
        let last_end = (snd last_region).Position.pos_cnum in
        LexReader.substring 
          reader last_end ((fst region).Position.pos_cnum - last_end)
      in
      (* token's string *)
      let substr = LexReader.current_substring reader in
      
      Cons ({ space = space_between; token; region; substr },
            lazy (match token with
            | EOF -> Null
            | _ -> loop region),
            ic)
    in
    loop Region.zero
  with
  | e -> raise e

let close = function
  | lazy Null -> ()
  | lazy (Cons (_, _, ic)) -> close_in ic

let destr = function
  | lazy Null -> None
  | lazy (Cons (car, cdr, _ic)) -> Some (car, cdr)