# atd-jsonlike

Generic JSON-like AST for use with ATD code generators.

## Overview

`atd-jsonlike` defines a simple AST type for representing JSON-like data
(JSON, YAML, TOML, …) with source location information attached to every
node.  Its primary consumer is [atdml](../atdml/): the `foo_of_jsonlike`
functions generated by `atdml` accept an `Atd_jsonlike.AST.t` value and
return a typed OCaml value, with error messages that include the original
file/line/column from the AST.

## Modules

### `AST`

```ocaml
type t =
  | Null   of Loc.t
  | Bool   of Loc.t * bool
  | Number of Loc.t * Number.t
  | String of Loc.t * string
  | Array  of Loc.t * t list
  | Object of Loc.t * (Loc.t * string * t) list
```

Every node carries a `Loc.t` so that reader functions can report precise
locations in error messages via `AST.loc_msg`.

`Object` entries also carry a per-key `Loc.t` for the key itself (the
outer `Loc.t` covers the whole key-value pair).

### `Number`

`Number.t` stores all available representations of a JSON number so that
readers can pick whichever form fits their target type:

```ocaml
type t = private {
  int:     int option;
  float:   float option;
  literal: string option;
}
```

| Source | `int` | `float` | `literal` |
|--------|-------|---------|-----------|
| `of_int 42` | `Some 42` | `Some 42.` | `Some "42"` |
| `of_float 1.5` | `None` | `Some 1.5` | `None` |
| `of_float 3.0` | `Some 3` | `Some 3.` | `None` |
| `of_string_opt "1.2e3"` | `None` | `Some 1200.` | `Some "1.2e3"` |
| `of_string_opt "1e400"` | `None` | `None` | `Some "1e400"` |

Rules enforced by the constructors:
- `literal`, when set, is always a valid JSON number string (no `+42`, no
  leading zeros, no `NaN`).
- All set fields are mutually consistent (same numeric value).
- At least one field is always set.

`of_float` does not populate `literal` because it operates on a binary
float that has already lost the original text.  Use `of_string_opt` when
you are parsing from source text and want to preserve the literal.

### `Loc` and `Pos`

`Loc.t` is a half-open source range (start + end `Pos.t`) plus an
optional file path.  `Pos.t` is a `{ row; column }` pair, both 0-based
(rows and columns are displayed as 1-based in error messages).

## Building and testing

```sh
cd atd-jsonlike
make        # build
make test   # run unit tests
```
