# Developing parsec

## Scope

`parsec` is a general token parser library. Keep protocol grammars, text
decoding, grammar-specific recovery, token trivia policy, and AST/CST lowering
in consumer packages. The root package is `Nanaloveyuki/parsec`; optional
packages extend it without sharing incompatible parser state.

The key behavioral rules are part of the public contract:

- `parse_all` must reject trailing input.
- `or_else` may backtrack only when the first branch consumed nothing.
- `attempt` can restore consumption but cannot revoke a `cut` commitment.
- `many` must reject a successful child parser that consumed nothing.
- `ParseError` offsets are token offsets.
- Retryable alternatives retain the furthest failure; same-offset expectations
  are merged as `ExpectedAny`.

## Local Setup

Install the current MoonBit toolchain. This project has no third-party
dependencies or native build prerequisites.

From the repository root, update the local registry and dependency cache:

```powershell
moon update
moon install
```

## Layout

```text
src/
  types.mbt          Public parser state and errors
  core.mbt           Construction, execution, and primitive token parsers
  transform.mbt      Value transformation and sequencing
  choice.mbt         Alternatives, retry, commitment, and error decoration
  repetition.mbt     Optional, repeated, separated, and delimited parsers
  lookahead.mbt      Positive and negative lookahead
  *_test.mbt         Behavior tests
  README.mbt.md      Package documentation and checked examples
  char/              Character parser factories over root Array[Char] parsers
  lazy/              Independent persistent pull-stream parser implementation
  lexer/             Source positions, spans, and located lexical values
  json/              Strict RFC 8259 document parser and limits
```

MoonBit packages are directory-based. Files directly inside `src/` form the
root package; each subdirectory with `moon.pkg` is a separate package. Split
files by responsibility, not by an assumed namespace.

`char` returns root parsers and therefore shares the root `Array[T]` input
model. `lazy` owns separate `Stream[T]`, `State[T]`, and `Parser[T, A]` types;
do not make either package depend on the other's private state. `lexer` owns
only source-location values and may depend on the public root `ParseError` API.
`json` may depend on root parser and lexer public APIs, but must not depend on
JSON5, JSON-RPC, JSONPath, JSONL, or another JSON parser. Keep its strict
syntax, duplicate-key policy, and resource limits inside the package.

`Reply[T, A]` is package-private. It records consumed and committed state so
`attempt`, `cut`, `or_else`, and repetition can make correct control-flow
decisions. Keep that representation private; external callers execute parsers
through `run`, `parse`, or `parse_all`.

## Validation

Run the narrowest relevant test while iterating, then run the full matrix
before review:

```powershell
moon fmt --check
moon check --target all
moon test --target all
moon info
git diff --check
```

`moon info` regenerates `src/pkg.generated.mbti`. Never edit that file by
hand. Review and commit its diff whenever the public API intentionally changes.

## Change Workflow

Create a focused branch from current `main`. Keep public API changes small,
add a behavior test for each semantic change, and update package and user
documentation when observable behavior changes.

Do not commit `_build`, `.mooncakes`, local tool caches, generated temporary
files, or machine-specific paths. The GitHub workflow is the authoritative
cross-platform gate and must pass before merge.
