///|
pub using @lexer {type Token, type LexError, tokenize}

///|
/// A statement passed through unchanged. `kind` is its lowercased leading
/// keyword and `line` the 1-based line of its first token.
pub struct Skip {
  kind : String
  line : Int32
} derive(Debug, Eq)

///|
pub extend Skip with @debug.Debug::{to_repr}

///|
pub extend Skip with Eq::{not_equal, equal}

///|
/// The result of `format`. `skips` has one entry per passed-through
/// statement, in source order.
pub struct Formatted {
  output : String
  skips : Array[Skip]
} derive(Debug)

///|
pub extend Formatted with @debug.Debug::{to_repr}

///|
pub fn Formatted::had_passthrough(self : Formatted) -> Bool {
  !self.skips.is_empty()
}

///|
/// Formats SQLite source in the river style.
///
/// Statements are separated by one blank line and the output ends in a
/// newline, unless the input has no tokens, in which case it is empty. Each
/// statement's leading comments are kept above it. A statement outside the
/// supported grammar is copied verbatim and reported in `skips`; it is not an
/// error.
///
/// ```mbt check
/// test {
///   let r = @sqlbrook.format("select a, b from t;")
///   inspect(
///     r.output,
///     content=(
///       #|select a
///       #|     , b
///       #|  from t
///       #|       ;
///       #|
///     ),
///   )
///   assert_false(r.had_passthrough())
/// }
/// ```
///
/// # Errors
/// Raises `LexError` when the input has a character that starts no token, an
/// unterminated quote, or PostgreSQL-only syntax (`::`, `$$`).
pub fn format(input : String) -> Formatted raise LexError {
  let skips = []
  let statements = []
  // Skips arrive in source order, so lines are counted in one pass.
  let mut line = 1
  let mut counted = 0
  for { comments, stmt, } in @syntax.parse(input, @lexer.lex(input)) {
    let body = @layout.render_stmt(stmt)
    statements.push(
      if comments.is_empty() {
        body
      } else {
        comments.join("\n") + "\n" + body
      },
    )
    if stmt is Passthrough(kind~, offset~, ..) {
      for i in counted..