Commits

camlspotter committed 04448c7

cleanup internal modules

Comments (0)

Files changed (23)

 # OASIS_START
 # DO NOT EDIT (digest: 8e57f046ce034f177cd68b56a3bde28f)
-version = "1.0.0"
+version = "1.1.0"
 description
  =
  "Planck(Parser LANguage Combinator Kit): a small parser combinator library"
 # OCamlGeneratedFiles(parser.ml lexer.ml)
 
 LIBFILES[] =
+   mtypes
    position
    result
    lazylist
 (** This is a lazy list basically, but its elements and nil can have extra information. *)
 
 type ('elem, 'attr) zlist = ('elem, 'attr) desc lazy_t
+
 and ('elem, 'attr) desc = 
   | Cons of 'elem * 'attr * ('elem, 'attr) zlist  (** cons of element with attribute *)
-  | Null of 'attr (** null with attribute *)
+  | Null of 'attr (** null with attribute. Even at the EOF, we can get some info of it, such as the position. *)
 
 (** Constructor functions *)
 val null : 'attr -> ('elem, 'attr) zlist
 
   open Open
 
-  let take : Str.elem t = fun s -> 
+  let take : Str.Elem.t t = fun s -> 
     Profile.incr ();
     match Str.peek s with
     | None -> Error (Str.position s, "unexpected end of stream")
   (* [take] advances the stream. If we use [take] and some predicate to check the result,
      the error position must be fixed as the one at the use of [take]. *)
 
-  let tokenp : (Str.elem -> bool) -> Str.elem t = fun p ->
+  let tokenp : (Str.Elem.t -> bool) -> Str.Elem.t t = fun p ->
     position >>= fun pos ->
     take >>= fun elem -> if p elem then return elem else error "tokenp" <?@> pos
 
-  let token_option : (Str.elem -> 'a option) -> 'a t = fun p ->
+  let token_option : (Str.Elem.t -> 'a option) -> 'a t = fun p ->
     position >>= fun pos ->
     take >>= fun elem -> 
     match p elem with
     | Some v -> return v
     | None -> error "tokenop" <?@> pos
 
-  let token_result : (Str.elem -> ('a, string) Result.t) -> 'a t = fun p ->
+  let token_result : (Str.Elem.t -> ('a, string) Result.t) -> 'a t = fun p ->
     position >>= fun pos ->
     take >>= fun elem ->
     match p elem with
     | Ok v -> return v
     | Error err -> error err <?@> pos
 
-  let token : Str.elem -> unit t = fun tkn ->
-    void (tokenp (fun x -> Str.equal_elem tkn x)) <?>  Str.show_elem tkn
+  let token : Str.Elem.t -> unit t = fun tkn ->
+    void (tokenp (fun x -> Str.Elem.equal tkn x)) <?>  Str.Elem.show tkn
 
   (* CR jfuruss: optimization oppotunity for char *)     
-  let one_of : Str.elem list -> Str.elem t = fun tkns ->
-    tokenp (fun x -> List.exists (Str.equal_elem x) tkns)
+  let one_of : Str.Elem.t list -> Str.Elem.t t = fun tkns ->
+    tokenp (fun x -> List.exists (Str.Elem.equal x) tkns)
     <?> Printf.sprintf "expected one of %s"
-         (String.concat " " (List.map Str.show_elem tkns))
+         (String.concat " " (List.map Str.Elem.show tkns))
 
-  let tokens : Str.elem list -> unit t = fun elems str ->
+  let tokens : Str.Elem.t list -> unit t = fun elems str ->
     Profile.incr ();
     let rec aux str = function
       | [] -> return () str
       | x::xs -> 
           match Str.peek str with
-          | Some (c,_,str') when Str.equal_elem c x -> aux str' xs
-          | _ -> error (Printf.sprintf "expected %s" (Str.show_elem x)) str
+          | Some (c,_,str') when Str.Elem.equal c x -> aux str' xs
+          | _ -> error (Printf.sprintf "expected %s" (Str.Elem.show x)) str
     in
     aux str elems
   
 (** The basic monadic parser module. See Planck_intf.ml for more details *)
 
 module Make( S : Stream_intf.S ) : Planck_intf.S
-  with type Str.elem = S.elem
-  and  module Str.Pos = S.Pos
-  and  type Str.attr = S.attr
+  with type Str.Elem.t = S.Elem.t
+  and  type Str.Pos.t  = S.Pos.t
+  and  type Str.Attr.t = S.Attr.t
   and  type 'a t = S.t -> ('a * S.t, S.Pos.t * string) Result.t
 (** Functor [Make] takes a stream implementation [S] and create a monadic parser module for [S].
     The parse uses the element, position and attribute from [S].
 
   external ok : ('a * Str.t) -> ('a * Str.t) = "%identity"
 
-  let take : Str.elem t = fun s -> match Str.peek s with
+  let take : Str.Elem.t t = fun s -> match Str.peek s with
     | None -> throw (Str.position s, "unexpected end of stream")
     | Some (elem, _pos, s') -> ok (elem, s')
 
   (* [take] advances the stream. If we use [take] and some predicate to check the result,
      the error position must be fixed as the one at the use of [take]. *)
 
-  let tokenp : (Str.elem -> bool) -> Str.elem t = fun p ->
+  let tokenp : (Str.Elem.t -> bool) -> Str.Elem.t t = fun p ->
     position >>= fun pos ->
     take >>= fun elem -> if p elem then return elem else error "tokenp" <?@> pos
 
-  let token_option : (Str.elem -> 'a option) -> 'a t = fun p ->
+  let token_option : (Str.Elem.t -> 'a option) -> 'a t = fun p ->
     position >>= fun pos ->
     take >>= fun elem -> 
     match p elem with
     | Some v -> return v
     | None -> error "tokenop" <?@> pos
 
-  let token_result : (Str.elem -> ('a, string) Result.t) -> 'a t = fun p ->
+  let token_result : (Str.Elem.t -> ('a, string) Result.t) -> 'a t = fun p ->
     position >>= fun pos ->
     take >>= fun elem ->
     match p elem with 
     | Ok v -> return v
     | Error mes -> error mes <?@> pos
 
-  let token : Str.elem -> unit t = fun tkn ->
-    void (tokenp (fun x -> tkn = x)) <?>  Str.show_elem tkn
+  let token : Str.Elem.t -> unit t = fun tkn ->
+    void (tokenp (fun x -> tkn = x)) <?>  Str.Elem.show tkn
 
-  let one_of : Str.elem list -> Str.elem t = fun tkns ->
+  let one_of : Str.Elem.t list -> Str.Elem.t t = fun tkns ->
     tokenp (fun x -> List.mem x tkns)
     <?> Printf.sprintf "expected one of %s"
-         (String.concat " " (List.map Str.show_elem tkns))
+         (String.concat " " (List.map Str.Elem.show tkns))
 
-  let tokens : Str.elem list -> unit t = fun elems str ->
+  let tokens : Str.Elem.t list -> unit t = fun elems str ->
     let rec aux str = function
       | [] -> return () str
       | x::xs -> 
           match Str.peek str with
           | Some (c,_,str') when c = x -> aux str' xs
-          | _ -> error (Printf.sprintf "expected %s" (Str.show_elem x)) str
+          | _ -> error (Printf.sprintf "expected %s" (Str.Elem.show x)) str
     in
     aux str elems
   
   let throw e = raise (Exn e)
   external ok : 'a -> 'a = "%identity"
 
-  let take : Str.elem t =  fun () -> match Str.peek !global_stream with
+  let take : Str.Elem.t t =  fun () -> match Str.peek !global_stream with
     | None -> throw (Str.position !global_stream, "unexpected end of stream")
     | Some (elem, _pos, s') -> 
         set s';
   (* [take] advances the stream. If we use [take] and some predicate to check the result,
      the error position must be fixed as the one at the use of [take]. *)
 
-  let tokenp : (Str.elem -> bool) -> Str.elem t = fun p ->
+  let tokenp : (Str.Elem.t -> bool) -> Str.Elem.t t = fun p ->
     position >>= fun pos ->
     take >>= fun elem -> if p elem then return elem else error "tokenp" <?@> pos
 
-  let token_option : (Str.elem -> 'a option) -> 'a t = fun p ->
+  let token_option : (Str.Elem.t -> 'a option) -> 'a t = fun p ->
     position >>= fun pos ->
     take >>= fun elem -> 
     match p elem with
     | Some v -> return v
     | None -> error "tokenop" <?@> pos
 
-  let token_result : (Str.elem -> ('a, string) Result.t) -> 'a t = fun p ->
+  let token_result : (Str.Elem.t -> ('a, string) Result.t) -> 'a t = fun p ->
     position >>= fun pos ->
     take >>= fun elem ->
     match p elem with 
     | Ok v -> return v
     | Error mes -> error mes <?@> pos
 
-  let token : Str.elem -> unit t = fun tkn ->
-    void (tokenp (fun x -> tkn = x)) <?>  Str.show_elem tkn
+  let token : Str.Elem.t -> unit t = fun tkn ->
+    void (tokenp (fun x -> tkn = x)) <?>  Str.Elem.show tkn
 
-  let one_of : Str.elem list -> Str.elem t = fun tkns ->
+  let one_of : Str.Elem.t list -> Str.Elem.t t = fun tkns ->
     tokenp (fun x -> List.mem x tkns)
     <?> Printf.sprintf "expected one of %s"
-         (String.concat " " (List.map Str.show_elem tkns))
+         (String.concat " " (List.map Str.Elem.show tkns))
 
-  let tokens : Str.elem list -> unit t = fun elems ->
+  let tokens : Str.Elem.t list -> unit t = fun elems ->
     let rec aux = function
       | [] -> return ()
       | x::xs -> 
           | Some (c,_,str') when c = x -> 
               set str';
               aux xs
-          | _ -> error (Printf.sprintf "expected %s" (Str.show_elem x))
+          | _ -> error (Printf.sprintf "expected %s" (Str.Elem.show x))
     in
     aux elems
   
 
 module Extend(Sbuffer : sig
   include Stream_intf.S
-  with type elem = char
-  and  type Pos.t = Position.File.t
+  with type Elem.t = char
+  and  type Pos.t  = Position.File.t
   val substr : t -> int -> int -> string * t
   val takeWhile : (char -> bool) -> t -> string * t
   val bytes : t -> int
 end)(Base : Planck_intf.S
-     with type Str.elem = Sbuffer.elem
-     and  type Str.attr = Sbuffer.attr
-     and  type Str.Pos.t = Sbuffer.Pos.t
+     with type Str.Elem.t = Sbuffer.Elem.t
+     and  type Str.Attr.t = Sbuffer.Attr.t
+     and  type Str.Pos.t  = Sbuffer.Pos.t
     ) = struct
 
   open Base
 
 module Extend(Sbuffer : sig
   include Stream_intf.S
-  with type elem = char
+  with type Elem.t = char
   and  type Pos.t = Position.File.t
   val substr : t -> int -> int -> string * t
   val takeWhile : (char -> bool) -> t -> string * t
   val bytes : t -> int
 end)(Base : Planck_intf.S 
-     with type Str.elem = Sbuffer.elem
-     and  type Str.attr = Sbuffer.attr
-     and  type Str.Pos.t = Sbuffer.Pos.t) : sig
+     with type Str.Elem.t = Sbuffer.Elem.t
+     and  type Str.Attr.t = Sbuffer.Attr.t
+     and  type Str.Pos.t  = Sbuffer.Pos.t) : sig
 
   (* CR jfuruse: we cannot write Base : Planck_intf.S with module Str = Sbuffer ! *)
 
 open Spotlib.Spot
 
 (* Interface for generic char stream. Not optimized. *)
-module Extend(Str : Stream_intf.S with type elem = char) (Base : Planck_intf.S 
-      with type Str.elem = char
-      and  type Str.attr = Str.attr
+module Extend(Str : Stream_intf.S with type Elem.t = char) (Base : Planck_intf.S 
+      with type Str.Elem.t = Str.Elem.t
+      and  type Str.Attr.t = Str.Attr.t
       and  type Str.Pos.t = Str.Pos.t)  = struct
 
   open Base
     end
 *)
 
-module Extend(Str : Stream_intf.S with type elem = char)
+module Extend(Str : Stream_intf.S with type Elem.t = char)
              (Base : Planck_intf.S 
-              with type Str.elem = char
-              and  type Str.attr = Str.attr
-              and  type Str.Pos.t = Str.Pos.t) :
+              with type Str.Elem.t = Str.Elem.t
+              and  type Str.Attr.t = Str.Attr.t
+              and  type Str.Pos.t  = Str.Pos.t) :
 sig
   val string : string -> unit Base.t
   (** [string s] succeeds if the prefix of the stream is [s]. *)
 
   (** Retrieve one stream element *)
 
-  val take : Str.elem t
+  val take : Str.Elem.t t
   val take_ : unit t
   (** Take the head token.
       [take_] is the same as [take], but the element is ignored. Following Haskell xxxM_ convention.
   *)
 
-  val token : Str.elem -> unit t
+  val token : Str.Elem.t -> unit t
   (** [token e] matches with the token [e] *)
-  val tokenp : (Str.elem -> bool) -> Str.elem t
+  val tokenp : (Str.Elem.t -> bool) -> Str.Elem.t t
   (** [tokenp p] matches with the token [e] where [p e = true]. *)
-  val token_option : (Str.elem -> 'a option) -> 'a t
+  val token_option : (Str.Elem.t -> 'a option) -> 'a t
   (** [token_option f] matches with the token [e] where [f e = Some v] for some [v], and  returns [v]. *)
-  val token_result : (Str.elem -> ('a, string) Result.t) -> 'a t
+  val token_result : (Str.Elem.t -> ('a, string) Result.t) -> 'a t
   (** Same as [token_option] but with customizable error messages *)
-  val one_of : Str.elem list -> Str.elem t
+  val one_of : Str.Elem.t list -> Str.Elem.t t
   (** [one_of tokens] matches with the token [e] where [List.mem e tokens = true] *)
 
 
 
-  val tokens : Str.elem list -> unit t
+  val tokens : Str.Elem.t list -> unit t
   (** [tokens elems] matches with a sequence of elements [elems]. 
       It is faster than using sequence of token. Tail recursion. 
   *)
   type key
   val memoize : key -> (t -> 'a) -> t -> 'a
 end )(Base : Planck_intf.S 
-      with type Str.elem = Str.elem
-      and  type Str.attr = Str.attr
-      and  type Str.Pos.t = Str.Pos.t) = struct
+      with type Str.Elem.t = Str.Elem.t
+      and  type Str.Attr.t = Str.Attr.t
+      and  type Str.Pos.t  = Str.Pos.t) = struct
 
   let memoize = Str.memoize
 end
   type key
   val memoize : key -> (t -> 'a) -> t -> 'a
 end )(Base : Planck_intf.S 
-      with type Str.elem = Str.elem
-      and  type Str.attr = Str.attr
-      and  type Str.Pos.t = Str.Pos.t) : sig 
+      with type Str.Elem.t = Str.Elem.t
+      and  type Str.Attr.t = Str.Attr.t
+      and  type Str.Pos.t  = Str.Pos.t) : sig 
   val memoize : Str.key -> (Str.t -> 'a) -> Str.t -> 'a 
 end
 (* Abstract position interface *)
 module type S = sig
   type t
-  val format : Format.formatter -> t -> unit
+  include Mtypes.Printable with type t := t
   val top : string -> t
   val none : t
 end
 
-module None = struct
+module None : S with type t = unit = struct
   type t = unit
   let format ppf () = Format.pp_print_string ppf "<no position>"
+  let show () = "<no position>"
   let top (_ : string) = ()
   let none = ()
 end
     column : int; (* in bytes from 0 *)
   } with sexp
 
+  include Mtypes.Printable with type t := t
+
   val top : string (* file name *) -> t
   val add_newlines : t -> int -> t
   val add_columns : t -> int -> t
   val none : t
-  val format : Format.formatter -> t -> unit
   val format_detailed : Format.formatter -> t -> unit
 end
 
   let add_newlines t n = { t with byte = t.byte + n; line = t.line + n; column = 0; }
   let add_columns t n = { t with byte = t.byte + n; column = t.column + n; }
   let none = { fname = ""; byte = -1; line = -1; column = -1; }
-  let format_filename ppf = function
-    | "" -> ()
-    | s -> Format.fprintf ppf "File %s:" s
+  let show_filename = function
+    | "" -> ""
+    | s -> Printf.sprintf  "File %s: " s
+  let show t = 
+    if t.byte < 0 then Printf.sprintf "%s<no location>" (show_filename t.fname)
+    else Printf.sprintf "%sline %d, character %d" (show_filename t.fname) t.line t.column
   let format ppf t = 
-    if t.byte < 0 then Format.fprintf ppf "<no location>"
-    else Format.fprintf ppf "%aline %d, character %d" format_filename t.fname t.line t.column
+    if t.byte < 0 then Format.fprintf ppf "%s<no location>" (show_filename t.fname)
+    else Format.fprintf ppf "%sline %d, character %d" (show_filename t.fname) t.line t.column
   let format_detailed ppf t = 
-    if t.byte < 0 then Format.fprintf ppf "<no location>"
-    else Format.fprintf ppf "%aline %d, character %d, byte %d" format_filename t.fname t.line t.column t.byte
+    if t.byte < 0 then Format.fprintf ppf "%s<no location>" (show_filename t.fname)
+    else Format.fprintf ppf "%sline %d, character %d, byte %d" (show_filename t.fname) t.line t.column t.byte
 
 end
 
 
 module Extend(Base : sig
   include S
-  with type elem = char
-  and  type Pos.t = Position.File.t
-  val create_attr : buf -> attr
+  with type Elem.t = char
+  and  type Pos.t  = Position.File.t
+  val create_attr : buf -> Attr.t
   val buf : t -> buf
 end) = struct
 
 
 module Extend(Base : sig
   include S
-  with type elem = char
-  and  type Pos.t = Position.File.t
+  with type Elem.t = char
+  and  type Pos.t  = Position.File.t
   (** Sbuffer is based on a stream whose element is [char].
       [attr] is implementation dependent.
   *)
-  val create_attr : buf -> attr
+  val create_attr : buf -> Attr.t
   val buf : t -> buf
 end) : sig
 
 (* open Stream_intf *)
 
 include Stream.Make(struct
-  type elem = string
-  let show_elem = Printf.sprintf "%S"
-  let equal_elem (x : string) y = x = y
-  type attr = unit
-  let default_attr = ()
+  module Elem = struct
+    type t = string
+    let show = Printf.sprintf "%S"
+    let format ppf = Format.fprintf ppf "%S"
+    let equal (x : string) y = x = y
+    let compare (x : string) y = compare x y
+  end
   module Pos = Position.None
-  let position_of_attr () = ()
+  module Attr = struct
+    type t = unit
+    let default = ()
+    let position () = Position.None.none
+  end
 end)
 
 let from_string str = Lazy.lazy_from_val (cons_desc str () (null ()))
 *)
 
 include Stream_intf.S
-  with type elem = string
-  and  type attr = unit
-  and  type Pos.t = unit
+  with type Elem.t = string
+  and  type Attr.t = unit
+  and  type Pos.t  = unit
 
 val from_string : string -> t
 
   open Lazylist
   include P
 
-  type t = (elem, attr) zlist
+  type t = (Elem.t, Attr.t) zlist
 
   let null = null
-  let default_null = null P.default_attr
+  let default_null = null P.Attr.default
   let null_desc = null_desc 
   let cons_desc = cons_desc
 
   let position t = 
     let desc = desc t in
     match desc with
-    | Null attr -> P.position_of_attr attr
-    | Cons (_elem, attr, _) -> P.position_of_attr attr
+    | Null attr -> P.Attr.position attr
+    | Cons (_elem, attr, _) -> P.Attr.position attr
 
 end
 open Stream_intf
 
 module Make (Base : Base) : S 
-  with module Pos = Base.Pos
-  and  type elem  = Base.elem
-  and  type attr  = Base.attr
+  with type Pos.t  = Base.Pos.t
+  and  type Elem.t = Base.Elem.t
+  and  type Attr.t = Base.Attr.t
 (** The functor [Make] creates a stream module based on [Base] *)
 
 
 (** Minimum specification to create a stream *)
 module type Base = sig
-  type elem
-  (** Type of the stream element *)
+  module Elem : sig
+    type t
+    (** Type of the stream element *)
 
-  val show_elem : elem -> string
-  (** [elem] must be printable *)
+    include Mtypes.Printable  with type t := t
+    include Mtypes.Comparable with type t := t
+  end
 
-  val equal_elem : elem -> elem -> bool
-  (** Element equality. 
-      If you can specify something more efficient than the polymorphic equality (=) here,
-      the entire parsing performance may be improved.
-  *)
-
-  type attr
-  (** Type of the stream attribute *)
-
-  val default_attr : attr
-  (** Default attr value *)
-    
   module Pos : Position.S
   (** Module for stream positions *)
 
-  val position_of_attr : attr -> Pos.t
-  (** [Pos.t] must be obtainable from [attr]. *)
+  module Attr : sig
+    type t
+    (** Type of the stream attribute *)
+
+    val default : t
+    (** Default attr value *)
+    
+    val position : t -> Pos.t
+    (** [Pos.t] must be obtainable from [t]. *)
+  end
 end
 
 (* Standard interface *)
 module type S = sig
   include Base
 
-  type t = (elem, attr) zlist
+  type t = (Elem.t, Attr.t) zlist
   (** Stream is implemented as a lazylist with attributes. *)
 
   val default_null : t
   (** Null with the default attr *)
 
-  val null : attr -> t
+  val null : Attr.t -> t
   (** Create a null stream *)
 
-  val null_desc : attr -> (elem, attr) desc
-  val cons_desc : elem -> attr -> t -> (elem, attr) desc
+  val null_desc : Attr.t -> (Elem.t, Attr.t) desc
+  val cons_desc : Elem.t -> Attr.t -> t -> (Elem.t, Attr.t) desc
   (** Create a null/cons cell desc. *)
 
 
   (** Destructors *)
-  val desc : t -> (elem, attr) desc
-  val peek : t -> (elem * attr * t) option
+  val desc : t -> (Elem.t, Attr.t) desc
+  val peek : t -> (Elem.t * Attr.t * t) option
 
   val is_null : t -> bool
   (** Null check *)
 
-  val attr : t -> attr
+  val attr : t -> Attr.t
   (** Attribute of the head element/null *)
 
   val position : t -> Pos.t
   (** Position of the head element/null *)
 
-  val to_list : t -> elem list
-  val to_list_with_attrs : t -> (elem * attr) list
+  val to_list : t -> Elem.t list
+  val to_list_with_attrs : t -> (Elem.t * Attr.t) list
   (** Conversions to eager list. The attribute at Null is thrown away. *)
 
-  val iter : (elem option -> attr -> unit) -> t -> unit
-  val fold_right : (elem option -> attr -> 'a -> 'a) -> t -> 'a -> 'a
-  val map : (elem -> attr -> 'a2 * 'attr2) -> (attr -> 'attr2) -> t -> ('a2, 'attr2) zlist
+  val iter : (Elem.t option -> Attr.t -> unit) -> t -> unit
+  val fold_right : (Elem.t option -> Attr.t -> 'a -> 'a) -> t -> 'a -> 'a
+  val map : (Elem.t -> Attr.t -> 'a2 * 'attr2) -> (Attr.t -> 'attr2) -> t -> ('a2, 'attr2) zlist
   (** Iteration, folding and map *)
 
-  val rev_between : t -> t -> (elem * attr) list
+  val rev_between : t -> t -> (Elem.t * Attr.t) list
   (** [rev_between t1 t2] returns the elemens between the two steam positions [t1] and [t2].
       [t2] must be a postfix of [t1].
       The elements are returned in the reverse order in the stream.
       This can be quite costy operation. Use with care.
   *)
 
-  val between : t -> t -> (elem * attr) list
+  val between : t -> t -> (Elem.t * Attr.t) list
   (** Same as [rev_between] but the elements are in the same ordered in the streams.
 
       [between t1 t2] is actually defined as [List.rev (rev_between t1 t2)].
   module Base = struct
 
     (* Stream elements *)
-    type elem = char (* It is a char stream *)
-    let show_elem = Printf.sprintf "%C" (* How to pretty print the element *)
-    let equal_elem (x : char) y = x = y
-
-    (* Stream attributes *)
-    type attr = Sbuffer.buf (* Stream elements carry internal buffers *)
-    let default_attr = Sbuffer.default_buf
+    module Elem = struct
+      type t = char (* It is a char stream *)
+      let show = Printf.sprintf "%C" (* How to pretty print the element *)
+      let format ppf = Format.fprintf ppf "%C" (* How to pretty print the element *)
+      let equal (x : char) y = x = y
+      let compare (x : char) y = compare x y
+    end
 
     (* Stream positions *)
     module Pos = Position.File (* Type of the element position *)
-    let position_of_attr attr = Sbuffer.position_of_buf attr (* How to obtain the position from attr *)
+
+    module Attr = struct
+      (* Stream attributes *)
+      type t = Sbuffer.buf (* Stream elements carry internal buffers *)
+      let default = Sbuffer.default_buf
+      let position attr = Sbuffer.position_of_buf attr (* How to obtain the position from attr *)
+    end
+
   end
 
   module Str = Stream.Make(Base) (* Build the stream *)