camlspotter avatar camlspotter committed a3d337d

comments for v1.0.0

Comments (0)

Files changed (14)

-(* This is a lazy list basically, but its elements and nil can 
-   have extra information.
-*)
+(** 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 | Null of 'attr
+and ('elem, 'attr) desc = 
+  | Cons of 'elem * 'attr * ('elem, 'attr) zlist  (** cons of element with attribute *)
+  | Null of 'attr (** null with attribute *)
 
-val null : 'elem -> ('attr, 'elem) zlist
-val null_desc : 'elem -> ('attr, 'elem) desc
+(** Constructor functions *)
+val null : 'attr -> ('elem, 'attr) zlist
+val null_desc : 'attr -> ('elem, 'attr) desc
 val cons_desc : 'elem -> 'attr -> ('elem, 'attr) zlist -> ('elem, 'attr) desc
 
 (** Destructors *)
 
 val iter : ('elem option -> 'attr -> 'c) -> ('elem, 'attr) zlist -> 'c
 val fold_right : ('elem option -> 'attr -> 'c -> 'c) -> ('elem, 'attr) zlist -> 'c -> 'c
-val map : ('elem -> 'attr -> 'c * 'd) ->('attr -> 'd) -> ('elem, 'attr) zlist -> ('c, 'd) zlist
+val map : ('elem -> 'attr -> 'c * 'd) -> ('attr -> 'd) -> ('elem, 'attr) zlist -> ('c, 'd) zlist
 
 val rev_between : ('elem, 'attr) zlist -> ('elem, 'attr) zlist -> ('elem * 'attr) list
 val between : ('elem, 'attr) zlist -> ('elem, 'attr) zlist -> ('elem * 'attr) list
-(* Tools for operator precedences and associativities *)
+(** Tools for operator precedences and associativities *)
+
+type 'a t
+(** This is the abstract type of ``unresolved parse tree''.
+
+    Type [s t] carries parse tree [s] whose operator precedences + associativities
+    are not fully resolved yet.
+
+    At parsing an expression with operators of type [s], 
+    first you can parse its sub-expressions from left to right 
+    without thinking about operator precedences or associativities. 
+    Instead, build [s t] instead of [s] using the combinators below.
+    Once the whole expression with operators is parsed as [s t], then
+    obtain the parse tree [s] by [build], which resolves all the necessary
+    operator precedences and associativities.
+
+    You can see a use example of this module at planck/test/expr.ml
+*)
 
 type op = {
-  prec : float;
-  kind : [ `Infix of [ `Left | `Right ] | `Noassoc | `Postfix | `Prefix ];
+  prec : float; (** Operator precedence. Bigger is stronger. *)
+  kind : [ `Infix of [ `Left | `Right ] (** Infix, left or right associative *)
+         | `Noassoc 
+         | `Postfix 
+         | `Prefix
+         ];
 }
 
 val tbl : (string, op) Hashtbl.t
+(** Operator table. The resolution functions below uses this table to query operators
+    and its precedence information *)
 
-type 'a t
+val find : (string -> op) ref
+(** By default [!find] is used to query operators from [tbl]. 
+    If your set of operators cannot use table based precedence + associativity query,
+    you can override this behavior by modifying the reference. 
+*)
+
+val terminal : 'a -> 'a t
+(** [terminal a] takes a terminal object and returns its unresolved tree.
+    Terminal objects are leaves in parse trees which cannot be affected by operators: 
+    ex. ``10'', ``"hello"'', ``var'' 
+*)
+  
+val parened : ('a -> 'a) -> 'a t -> 'a t
+(** [parened f at] creates the unresolved parse tree for the parenthesized expression
+    which [at] represents. For example, if [at] represents ``1 + 2'', [parened f at]
+    represents ``(1 + 2)''. At resolution, the result of [at] is given to the funciton 
+    [f] to create the result of [parened f at].
+*)
+
+val infix : string -> ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
+(** [infix name f at1 at2] creates the unresolved parse tree for the expression
+    of a binary operator use [name] whose left argument is [at1] and right is [at2].
+    At resolution, the precedence and associativity of [name] is obtained from [find]
+    function above. Function [f] is used to create the result of the resolution. *)
+
+val prefix : string -> ('a -> 'a) -> 'a t -> 'a t
+(** [prefix name f at] creates the unresolved parse tree for the expression
+    prefixed by an operator [name] whose argument is [at].
+    At resolution, the precedence and associativity of [name] is obtained from [find]
+    function above. Function [f] is used to create the result of the resolution. *)
+
+val postfix : string -> ('a -> 'a) -> 'a t -> 'a t
+(** [postfix name f at] is just like [prefix name f at], but for postfix operators. *)
+
+val list : string -> ('a list -> 'a) -> 'a t list -> 'a t
+(** [list name f ats] creates the unresolved parse tree for the list style expression
+    which is separated by the operator [name] and has the elements [ats]. *)
 
 val build : 'a t -> 'a
-val terminal : 'a -> 'a t
-val parened : ('a -> 'a) -> 'a t -> 'a t
-val infix : string -> ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
-val prefix : string -> ('a -> 'a) -> 'a t -> 'a t
-val postfix : string -> ('a -> 'a) -> 'a t -> 'a t
-val find : (string -> op) ref
-val list : string -> ('a list -> 'a) -> 'a t list -> 'a t
+(** [build at] analyzes all the required precedencies + associativities in 
+    the unresolved parse tree [at] and returns the resolution result. *)
+(** 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
   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].
+    The monad is a function type [S.t -> ('a * S.t, S.Pos.t * string) Result.t].
+*)
+(** Experimental base module, which could be a replacement of Pbase. 
+    
+    Here, the base monad is not using the result monad, but errors are reported by exception.
+    So far, there is no big difference of performance between Pbase and Pbaseexn.
+*) 
+
 open Spotlib.Spot
 open Planck_intf
 open Result
+(** Experimental base module, which could be a replacement of Pbase. 
+    
+    Here, the base monad is not using the result monad, but errors are reported by exception.
+    Streams are not given by function arguments but from the global reference [global_stream].
+    So far, there is no big difference of performance between Pbase and Pbaseref.
+*) 
+
 open Spotlib.Spot
 open Planck_intf
 open Result
+(** Monadic parser for buffered char streams *)
+
 open Sbuffer
 
 (** Extend(Str)(Base) extends Base for Str with buffered string operations
+(** Monadic parser for char stream *)
+
 (** Extend(Str)(Base) extends Base for Str with string operations
     Typical usage is:
 
+(** Monadic parser interface *)
+
 open Spotlib.Spot
 
 module type S = sig
   (** Underlied stream *)
 
   type error = Str.Pos.t * string
+  (** Error is a pair of a source position and a message string. *)
 
   exception Critical_error of error
   (** Exception of critical error. Used for non recoverable errors. *)
 
+  (** Profiling purpose to count closure constructions. *)
   module Profile : sig
     val incr : unit -> unit
     val format : Format.t -> unit
   end
 
   include Monad_intf.T 
-  (** Monadic interface. ['a t] is a function, so \eta expandable *)
+  (** Inherit monadic interface. ['a t] is a function, so \eta expandable *)
 
   (** Parser combinators *)
 
+
+
+  (** Retrieve one stream element *)
+
   val take : Str.elem 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
+  (** [token e] matches with the token [e] *)
+  val tokenp : (Str.elem -> bool) -> Str.elem t
+  (** [tokenp p] matches with the token [e] where [p e = true]. *)
+  val token_option : (Str.elem -> '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
+  (** Same as [token_option] but with customizable error messages *)
+  val one_of : Str.elem list -> Str.elem t
+  (** [one_of tokens] matches with the token [e] where [List.mem e tokens = true] *)
+
+
+
+  val tokens : Str.elem list -> unit t
+  (** [tokens elems] matches with a sequence of elements [elems]. 
+      It is faster than using sequence of token. Tail recursion. 
+  *)
+
+
+
+  (** Failure recovery *)
+    
+  val option : 'a t -> 'a option t
+  (** [option a] returns [Some v] if [a] succeeds and returns [v]. Otherwise, [option a] returns [None] *)
+  val option_ : unit t -> unit t
+  (** [option_ a] tries matching [a]. 
+      No matter whether [a] succeeds or not, [option_ a] is always successful and returns [()]. *)
+  val result : 'a t -> ('a, error) Result.t t
+  (** [result a] is as same as [option a] but [error] instead of [None] at error. *)
+
+  val try_finally : 'a t -> (('a, error) Result.t -> unit) -> 'a t
+  (** [try_finally t f] performs [t] then run [f] over the result of [t], 
+      no matter whether it succeeds or not. The result of the expression is the result of [t].
+  *)
+
+
+
+  (** Surrounded / listed *)
+    
+  val surrounded : 'a t -> 'b t -> 'c t -> 'c t
+  (** [surrounded left right content] is for [content] prefixed by [left] and postfixed by [right] *)
+  (* CR jfuruse: 'a t and 'b t are too general. unit t ? *)
+  (* CR jfuruse: labels ? *)
+
+  val list_with_sep : ?optional_head:bool -> sep:unit t -> 'a t -> 'a list t
+  (** [list_with_sep ?optional_head ~sep a] is for parsing list of [a] separated by [sep].
+      If [optional_head] is true, the list can have optional head separator like ``| A | B | C''.
+      Otherwise, the separator must strictly occur between elements, like ``A | B | C''. *) 
+
+
+
+  (** Choice and backtrack *)
+
+  val ( <|> ) : 'a t -> 'a t -> 'a t
+  (** Parsec's <|>. 
+      [a <|> b] first tries [a]. If [a] succeeds, returns it results as the result of the whole expression.
+      If [a] fails WITHOUT consuming any input, [b] is tried. 
+      If [a] fails using comsuming some input, its error is used as the result of the whole.
+  *)
+
+  val try_ : 'a t -> 'a t
+  (** Parsec's try. Any failure of [try_ a] is reported as if it did not consume any input. *)
+  (** CR jfuruse: _ is used as convention for unit monad, but here, used for avoid name crash... *)
+
+  (** With backtracks *)
+  val ( <!> ) : 'a t -> 'a t -> 'a t
+  (** Backtrack, unlike [<|>]. (try_ a <|> b) == (a <!> b)
+
+      [a <!> b] first tries [a]. If [a] succeeds, returns it results as the result of the whole expression.
+      If [a] fails, no matter whether it consuming any input or not, [b] is tried. 
+
+      Be careful. Careless uses of [<!>] slow down parser efficiency, a lot.
+      If you have to use it, think about memoization.
+  *)
+
+  val ( <&> ) : 'a t -> ('a -> 'b t) -> 'b t
+  (** For push back. [t <&> f] is like [t >>= f], but the result monad's stream position
+      is the same as [t]. 
+
+      [a <&> f] first tries [a]. If [a] fails, the entire expression fails.
+      If [a] succeeds, [f] is run over the same input [a] takes.
+  *)
+
+
+
+  (** `*' and `+' operators of Regexp
+
+      NOTE: It is not Regexp. It has no backtrack:
+      [?* (token A) >>= fun () -> token A] does not match AAA, since [?* (token A)] eats all the AAA,
+      and nothing is left for the latter [token A].
+  *)
+  val ( ?** ) : 'a t -> 'a list t
+  val ( ?* )  : 'a t -> unit t
+  (** [?** a] matches with zero or more sequence of [a]. *)
+
+  val ( ?++ ) : 'a t -> 'a list t
+  val ( ?+ )  : 'a t -> unit t
+  (** [?++ a] matches with one or more sequence of [a]. *)
+
+
+
+  (** Regex style operators with backtrack 
+
+      Warn: it performs backtrack and could be very slow. 
+      Warn: not tested well at all.
+  *)
+  val ( /**/ ) : 'a list t -> 'a list t -> 'a list t (** not tail rec *)
+  val ( /*/ ) : unit t -> unit t -> unit t
+  val ( /++/ ) : 'a list t -> 'a list t -> 'a list t (** not tail rec *)
+  val ( /+/ ) : unit t -> unit t -> unit t
+  val ( /?/ ) : 'a list t -> 'a list t -> 'a list t
+
+
+
+  (** Errors *)
+    
+  val error : string -> 'a t
+  (** [error mes] fails with the error message [mes].
+      The error can be caught by other combinators like [<|>] and [<!>].
+  *)
+
+  val throw : error -> 'a t
+  (** same as [error] but with position *)
+
+  val critical_error : Str.Pos.t -> string -> 'a t
+  (** Raise the critical error exception. The exception must be caught by [try ... with].
+
+      Note: The exception is raised when the monad is executed.
+      Therefore, it cannot be caught at the monad construction time. It must be caught at the execution.
+  *)
+
+  val critical : 'a t -> 'a t
+  (** If [t] fails, [critical t] reports its error as a critical error exception *)
+
+
+
+  (** Error messages and positions *)
+
+  val ( <?!> ) : 'a t -> string -> 'a t
+  (** Enrich error: [m <?!> mes] returns an error message [mes] at error *)
+
+  val ( <?> ) : 'a t -> string -> 'a t
+  (** Enrich error: [m <?> mes] returns an error message ["expected " ^ mes] at error *)
+
+  val ( <?@> ) : 'a t -> Str.Pos.t -> 'a t
+  (** [m <?@> pos] changes the position of error of [m] to [pos], if happens *)
+
+
+
+  (** Streams *)
+
   val stream : Str.t t
   (** return the underlying stream of the current position *)
 
   val position : Str.Pos.t t
   (** Returns the position of the head token in the stream. *)
 
-  val error : string -> 'a t
-  (** [error mes] fails with the error message [mes].
-      The error can be covered by other combinators like [<|>] and [<!>].
-  *)
 
-  val throw : error -> 'a t
 
-  val critical_error : Str.Pos.t -> string -> 'a t
-  (** Raise the critical error exception. The exception must be caught by [try ... with].
-
-      Note: The exception is raised when the monad is executed.
-      Therefore, it cannot be caught at the monad construction time. It must be caught at the execution.
-  *)
-
-  val throw : error -> 'a t
-  (** same as [error] but with position *)
+  (** End of stream *)
 
   val eos : unit t
   (** Matches with End Of Stream *)
-
-  val token : Str.elem -> unit t
-  (** [token e] matches with the token [e] *)
-
-  val tokenp : (Str.elem -> bool) -> Str.elem t
-  (** [tokenp p] matches with the token [e] where [p e = true]. *)
-
-  val token_option : (Str.elem -> '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
-  (** Same as [token_option] but with customizable error messages *)
-
-  val one_of : Str.elem list -> Str.elem t
-
-  val tokens : Str.elem list -> unit t
-  (** Tail rec. Faster than using sequence of token *)
-
-  val option : 'a t -> 'a option t
-  val option_ : unit t -> unit t
-  val result : 'a t -> ('a, error) Result.t t
-
-  val try_finally : 'a t -> (('a, error) Result.t -> unit) -> 'a t
-  (** [try_finally t f] performs [t] then run [f] over the result of [t].
-      The result of the expression is the result of [t].
-  *)
-
-  val surrounded : 'a t -> 'b t -> 'c t -> 'c t
-  (** ['b t] must not accept ['c t] *)
-
-  val list_with_sep : ?optional_head:bool -> sep:unit t -> 'a t -> 'a list t
-
-  (** `*' and `+' operators of Regexp
-
-      NOTE: It is without backtrack:
-      [?* (token A) >>= fun () -> token A] does not match AAA, since [?* (token A)] eats all the AAA,
-      and nothing is left for the latter [token A].
-  *)
-  val ( ?** ) : 'a t -> 'a list t
-  val ( ?* )  : 'a t -> unit t
-  val ( ?++ ) : 'a t -> 'a list t
-  val ( ?+ )  : 'a t -> unit t
-
-  val critical : 'a t -> 'a t
-  (** If [t] fails, [critical t] reports its error as a critical error exception *)
-
-  val ( <?!> ) : 'a t -> string -> 'a t
-  (** Enrich error: [m <?!> mes] returns an error message [mes] at error *)
-
-  val ( <?> ) : 'a t -> string -> 'a t
-  (** Enrich error: [m <?> mes] returns an error message ["expected " ^ mes] at error *)
-
-  val ( <?@> ) : 'a t -> Str.Pos.t -> 'a t
-  (** [m <?@> pos] changes the position of error of [m] to [pos], if happens *)
-
-  val ( <|> ) : 'a t -> 'a t -> 'a t
-  (** Parsec's <|>. The right is tried only when the left fails without consuming any input *)
-
-  val try_ : 'a t -> 'a t
-  (** Parsec's try *)
-
-  (** With backtracks *)
-  val ( <!> ) : 'a t -> 'a t -> 'a t
-  (** Unlike [<|>], it performs full backtracks.
-      (try_ a <|> b) == (a <!> b)
-  *)
-
   val eos_as_none : 'a t -> 'a option t
   (** End of stream is reported as None *)
 
-  val ( <&> ) : 'a t -> ('a -> 'b t) -> 'b t
-  (** For push back. [t <&> f] is like [t >>= f], but the result monad's stream position
-      is the same as [t]. *)
 
-  (** Regex style operators *)
 
-  val ( /**/ ) : 'a list t -> 'a list t -> 'a list t
-    (** not tail rec *)
-  val ( /*/ ) : unit t -> unit t -> unit t
-  val ( /++/ ) : 'a list t -> 'a list t -> 'a list t
-    (** not tail rec *)
-  val ( /+/ ) : unit t -> unit t -> unit t
-  val ( /?/ ) : 'a list t -> 'a list t -> 'a list t
-
+  (** Misc *)
+    
   val begin_with : 'a t -> 'b t -> 'b option t
   (** [begin_with b w]: if [b] matches then try [w] and returns [w]'s result.
       Otherwise, it returns [None]. *)
+  (* CR jfuruse: should be removed *)
+
+
+  (** Monad runner *)
 
   val run : 'a t -> Str.t -> ('a * Str.t, error) Result.t
   (** Run the monad over the stream *)
+(** Parser module extension for memoization over stream *)
+
 (** Extend(Str)(Base) extends Base for Str with memoization
     Typical usage is:
 
-(* Result monad: Haskell's Either but with ``Right'' names. *)
+(** Result monad: Haskell's Either but with ``Right'' names. *)
 
 open Spotlib.Spot
 
+(** Stream module extention for memoization *)
+
 (** Extend(Base) extends Base with memoization over each stream element.
     Typical usage is:
 
-(* positionless string stream, used for Sbuffer *)
+(** Positionless string stream (not char stream), used for Sbuffer *)
 
 include Stream_intf.S
   with type elem = string
+(** Stream module. See Stream_intf for more details *)
 open Stream_intf
 
 module Make (Base : Base) : S 
   with module Pos = Base.Pos
   and  type elem  = Base.elem
   and  type attr  = Base.attr
+(** The functor [Make] creates a stream module based on [Base] *)
 
+(** Stream interface *)
+
 open Spotlib.Spot
 open Lazylist
 
   (** [elem] must be printable *)
 
   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 *)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.