(******************************************************************************)
(*                                                                            *)
(*                                    Menhir                                  *)
(*                                                                            *)
(*   Copyright Inria. All rights reserved. This file is distributed under     *)
(*   the terms of the GNU Library General Public License version 2, with a    *)
(*   special exception on linking, as described in the file LICENSE.          *)
(*                                                                            *)
(******************************************************************************)

open Lexing

(**This module offers functions that can help produce syntax error messages. *)

(* -------------------------------------------------------------------------- *)

(**A two-place buffer of type ['a buffer] holds zero, one, or two elements of
   type ['a]. Some of the functions below keep track of the start and end
   positions of the last two tokens in a two-place buffer. This helps nicely
   show where a syntax error took place. *)
type 'a buffer

(**[wrap lexer] returns a pair of a new (initially empty) buffer and a lexer
   which internally relies on [lexer] and updates [buffer] on the fly whenever
   a token is demanded.

   The type of the buffer is [(position * position) buffer], which means that
   it stores two pairs of positions, which are the start and end positions of
   the last two tokens.

   The type of the lexer is [lexbuf -> 'token]. The start and end positions
   of each token are read from [lexbuf]. *)
val wrap:
  ((lexbuf -> 'token) as 'lexer) ->
  (position * position) buffer * 'lexer

(**[wrap_supplier] is analogous to {!wrap}, except the type of the lexer is
   [unit -> 'token * position * position]. No [lexbuf] is involved. *)
val wrap_supplier:
  ((unit -> 'token * position * position) as 'lexer) ->
  (position * position) buffer * 'lexer

(**[show f buffer] prints the contents of the buffer, producing a string that
   is typically of the form "after '%s' and before '%s'". The function [f] is
   used to print an element. The buffer MUST be nonempty. *)
val show: ('a -> string) -> 'a buffer -> string

(**[last buffer] returns the last element of the buffer. The buffer MUST be
   nonempty. *)
val last: 'a buffer -> 'a

(* -------------------------------------------------------------------------- *)

(**[extract text (pos1, pos2)] extracts the sub-string of [text] delimited
   by the positions [pos1] and [pos2]. *)
val extract: string -> position * position -> string

(**[sanitize text] eliminates any special characters from the text [text].
   A special character is a character whose ASCII code is less than 32.
   Every special character is replaced with a single space character. *)
val sanitize: string -> string

(**[compress text] replaces every run of at least one whitespace character
   with exactly one space character. *)
val compress: string -> string

(**[shorten k text] limits the length of [text] to [2k+3] characters. If the
   text is too long, a fragment in the middle is replaced with an ellipsis. *)
val shorten: int -> string -> string

(**[expand f text] searches [text] for occurrences of [$k], where [k]
   is a nonnegative integer literal, and replaces each such occurrence
   with the string [f k]. *)
val expand: (int -> string) -> string -> string
