///| 源码位置 — 解析过程中追踪的位置信息。

///|

///| 同时追踪行号、列号和字节偏移,使错误信息可以指向精确的可读位置,

///| 同时偏移量支持对输入字符串的 O(1) 切片。

///|

///| Source position tracked during parsing.

///| Tracks line, column, and byte-offset simultaneously so error messages

///| can point to an exact human-readable location while offset enables

///| O(1) slicing into the input string.

///|

///| - `line` — 1 起始的行号,遇到 `'\n'` 递增

///| - `column` — 1 起始的列号,遇到 `'\n'` 重置为 1

///|
/// - `offset` — 0 起始的字节偏移
#derive(Eq, Debug)
pub(all) struct Pos {
  mut line : Int32
  mut column : Int32
  mut offset : Int32
}

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

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

///| 创建初始位置(行 1,列 1,偏移 0)。

///|

///|
/// Create the initial position (line 1, column 1, offset 0).
pub fn Pos::initial() -> Pos {
  { line: 1, column: 1, offset: 0, }
}

///| 将位置前进一个字符。

///|

///| - 若 `ch` 为 `'\n'`,行号递增、列号重置为 1

///| - 否则列号递增 1

///| - 偏移量始终递增 1

///|

///| 返回一个**新的** Pos,原对象不被修改。

///|

///| Advance the position by one character.

///|
/// Returns a **new** Pos; the original is not mutated.
pub fn Pos::advance(self : Pos, ch : Char) -> Pos {
  if ch == '\n' {
    { line: self.line + 1, column: 1, offset: self.offset + 1, }
  } else {
    { line: self.line, column: self.column + 1, offset: self.offset + 1, }
  }
}

///| 可变解析状态 — 包装输入字符串和游标。

///|

///| 每个 `Parser.run` 接收一个 `State`,可以修改它(推进游标),

///| 并返回携带(可能已前进的)状态的 `ParseResult`。

///|

///| Mutable parsing state that wraps the input string and a cursor.

///| Each `Parser.run` receives a `State`, may mutate it (advance the cursor),

///| and returns a `ParseResult` carrying the (possibly advanced) state forward.

///|

///| - `input` — 完整输入字符串,构造后不可变

///| - `offset` — 当前读取位置(字节偏移)

///|
/// - `pos` — 当前可读位置(行、列、偏移)
#derive(Debug)
pub(all) struct State {
  input : String
  mut offset : Int32
  mut pos : Pos
}

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

///| 创建一个位于 `input` 起始位置的新 `State`。

///|

///|
/// Create a fresh `State` positioned at the start of `input`.
pub fn State::new(input : String) -> State {
  { input, offset: 0, pos: Pos::initial(), }
}

///| 从当前偏移到输入末尾的剩余字符数。

///|

///|
/// Number of characters remaining from the current offset to end-of-input.
pub fn State::remaining(self : State) -> Int32 {
  self.input.length() - self.offset
}

///| 游标是否已到达或越过输入末尾。

///|

///|
/// True when the cursor has reached or passed the end of input.
pub fn State::is_eof(self : State) -> Bool {
  self.offset >= self.input.length()
}

///| 查看游标下方的字符,不推进游标。

///|

///| 未到 EOF 返回 `Some(ch)`,否则返回 `None`。

///|

///| Peek at the character under the cursor without advancing.

///|
/// Returns `Some(ch)` if not at EOF, `None` otherwise.
pub fn State::peek(self : State) -> Char? {
  if self.is_eof() {
    None
  } else {
    self.input.get_char(self.offset)
  }
}

///| 将游标前进一个字符,更新位置追踪。

///|

///| 已在 EOF 时无操作。

///|

///| Advance the cursor by exactly one character, updating position tracking.

///|
/// No-op when already at EOF.
pub fn State::advance_one(self : State) -> Unit {
  if !self.is_eof() {
    let ch = self.input.get_char(self.offset).unwrap()
    self.pos = self.pos.advance(ch)
    self.offset = self.offset + 1
  }
}

///| 将游标前进 `n` 个字符,更新位置追踪。

///|

///| 等价于调用 `advance_one` `n` 次。

///| 调用者必须确保 `n <= remaining()`。

///|

///| Advance the cursor by `n` characters, updating position tracking.

///| Equivalent to calling `advance_one` `n` times.

///|
/// Caller must ensure `n <= remaining()`.
pub fn State::advance_by(self : State, n : Int32) -> Unit {
  for _ in 0.. String {
  self.input[start:end].to_owned()
}

///| 解析错误 — 携带位置、期望词元和承诺状态。

///|

///| `committed` 标志实现了 Angstrom 的承诺语义:

///|

///| - `committed = false` — 解析器未消耗有效输入,`alt` 可尝试下一个备选(允许回溯)

///| - `committed = true` — 解析器已消耗有效输入,`alt` **不会**尝试下一个备选(禁止回溯)

///|

///| 承诺由以下方式设定:

///| - `commit(p)` — 显式将 `p` 的失败标记为已承诺

///| - `bind` / `seq2` / `seq3` / `seq4` — 若第二个解析器失败,错误被承诺("序列承诺")

///|

///| A parse error carrying position, expected tokens, and commitment status.

///| The `committed` flag implements Angstrom's commitment semantics:

///| - `committed = false` — backtracking is allowed in `alt`

///|
/// - `committed = true` — backtracking is suppressed in `alt`
#derive(Debug, Eq)
pub(all) struct ParseError {
  pos : Pos
  expected : Array[String]
  committed : Bool
  context : String
}

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

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

///| 在 `pos` 处构造一个未承诺的错误,期望 `expected`。

///|

///| 便捷工厂:单个期望词元、无上下文、未承诺。

///|

///| Construct an uncommitted error at `pos` expecting `expected`.

///|
/// Convenience factory for the common case: single expected token, no context, uncommitted.
pub fn ParseError::at(pos~ : Pos, expected~ : String) -> ParseError {
  { pos, expected: [expected], committed: false, context: "", }
}

///| 返回 `committed = true` 的副本,用于序列承诺语义。

///|

///|
/// Return a copy with `committed = true`, used for sequence-commit semantics.
#inline
pub fn ParseError::commit(self : ParseError) -> ParseError {
  {
    pos: self.pos,
    expected: self.expected,
    committed: true,
    context: self.context,
  }
}

///| 将错误格式化为人类可读的字符串。

///|

///| 输出格式:

///| ```text

///| line L, column C (offset O):

///| expected X or Y

///|   context-label

///| ```

///|

///| 多个 `expected` 条目用 `" or "` 连接。`context` 为空时省略。

///|

///| Format this error as a human-readable string.

///| Multiple `expected` entries are joined with `" or "`.

///|
/// The `context` line is omitted when empty.
pub fn ParseError::format(self : ParseError) -> String {
  let loc = "line \{self.pos.line}, column \{self.pos.column} (offset \{self.pos.offset})"
  let exp = self.expected.join(" or ")
  let ctx = if self.context == "" { "" } else { "\n  \{self.context}" }
  "\{loc}:\nexpected \{exp}\{ctx}"
}

///| 将错误格式化,并附加从 `input` 提取的上下文片段。

///|

///| 生成与 `format()` 相同的头部,加上显示错误位置前后各最多 20 个字符的片段:

///|

///| ```text

///| line 3, column 15 (offset 42):

///| expected HTTP method

///|   ...GET /path with-Payload...

///|                ^

///| ```

///|

///| Format this error with a context snippet extracted from `input`.

///| Produces the same header as `format()`, plus a snippet line showing

///|
/// up to 20 characters before and after the error position.
pub fn ParseError::format_with_input(
  self : ParseError,
  input : String,
) -> String {
  let base = self.format()
  let offset = self.pos.offset
  let ctx_start = if offset > 20 { offset - 20 } else { 0 }
  let ctx_end = if offset + 20 < input.length() {
    offset + 20
  } else {
    input.length()
  }
  let snippet = input[ctx_start:ctx_end].to_owned()
  let prefix = if ctx_start > 0 { "..." } else { "" }
  let suffix = if ctx_end < input.length() { "..." } else { "" }
  let caret_offset = offset - ctx_start + prefix.length()
  let caret = " ".repeat(caret_offset) + "^"
  "\{base}\n  \{prefix}\{snippet}\{suffix}\n  \{caret}"
}

///| 解析结果 — 运行 `Parser[T]` 后的输出。

///|

///| - `Success(value, state)` — 匹配成功;`value` 为解析结果,`state` 为消耗后的游标位置

///| - `Failure(error)` — 匹配失败;`error` 携带位置和承诺信息,供 `alt` 回溯决策

///|

///| The result of running a `Parser[T]` against a `State`.

///| - `Success(value, state)` — matched successfully

///|
/// - `Failure(error)` — failed; `error` carries position and commitment for `alt`
pub(all) enum ParseResult[T] {
  Success(T, State)
  Failure(ParseError)
}

///| 位置感知解析器组合子。

///|

///| 包装函数 `State -> ParseResult[T]`,尝试在当前游标位置匹配输入。

///| 组合子(`map`、`bind`、`alt`、`seq2` 等)将 `Parser` 组合为更大的解析器,

///| 无需暴露内部 `State` 机制。

///|

///| 使用 `Parser::parse` 进行简单解析,或 `Parser::parse_full` 要求全部输入被消耗。

///|

///| A position-aware parser combinator.

///| Wraps a function `State -> ParseResult[T]` that attempts to match input

///| at the current cursor position. Combinators compose `Parser` values

///|
/// into larger parsers without exposing the internal `State` machinery.
pub(all) struct Parser[T] {
  run : (State) -> ParseResult[T]
}

///| 将原始函数包装为 `Parser[T]` — 通用扩展点。

///|

///|
/// Wrap a raw function into a `Parser[T]` — the universal extension point.
pub fn[T] Parser::of(f : (State) -> ParseResult[T]) -> Parser[T] {
  { run: f, }
}

///| 解析 `input`,允许尾部未消耗的输入。

///|

///| 这是最宽松的入口:只要解析器匹配了 `input` 的前缀即成功。

///| 需要确保全部输入被消耗时使用 `parse_full`。

///|

///| Parse `input` and return the result, allowing trailing unconsumed input.

///|
/// Use `parse_full` when you need to ensure the entire input is consumed.
pub fn[T] Parser::parse(
  self : Parser[T],
  input : String,
) -> Result[T, ParseError] {
  let state = State::new(input)
  match (self.run)(state) {
    Success(value, _) => Ok(value)
    Failure(err) => Err(err)
  }
}

///| 解析 `input`,要求全部输入被消耗。

///|

///| 类似 `parse`,但若解析器成功却未到达 EOF,

///| 返回 `Err` 且 `expected = "end of input"`。

///|

///| Parse `input` and require that the entire input is consumed.

///|
/// If the parser succeeds without reaching EOF, returns an `Err`.
pub fn[T] Parser::parse_full(
  self : Parser[T],
  input : String,
) -> Result[T, ParseError] {
  let state = State::new(input)
  match (self.run)(state) {
    Success(value, st) =>
      if st.is_eof() {
        Ok(value)
      } else {
        Err(ParseError::at(pos=st.pos, expected="end of input"))
      }
    Failure(err) => Err(err)
  }
}