first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# `parser`
## Purpose
CDDL parser per RFC 8610 §3 grammar. Consumes the token stream from the
`tokenize` function and produces a typed AST (`CddlAst`) that the validator
walks. Supports the working subset of CDDL needed by real consumers (CWT,
COSE_Sign1, WebAuthn attestation, vault manifests, drive templates).
## Features
- Rule definitions: `name = T`, `name<T> = ...` (generic params).
- Type expressions: primitive prelude, named references, generic instantiation.
- Type composition: choice (`/`), inclusive (`..`) + exclusive (`...`) ranges,
parenthesised grouping.
- Group composition: arrays (`[ ... ]`), maps (`{ ... }`), occurrence
indicators (`?`, `*`, `+`, `*N`, `M*N`, `M*`), group choice (`//`).
- Map keys: identifier-`:`-T (text key), `"quoted":` T (text key with quoted
syntax), `<int> => T` (numeric key), `"quoted" => T`.
- Tagged items: `#6.<tag>(T)` produces `{ kind: "tagged", tag, inner }`.
- Literal values: text strings, byte strings (`h'…'`), integers (positive and
negative), `true`/`false`, `null`/`nil`, `undefined`.
- Control operators applied to types: `tstr .size 1..32`, `tstr .regexp "pattern"`,
`bstr .cbor T`. Both literal and range right-hand sides supported on `.size`.
## Usage: Basic Example
```ts
import { parseCddl } from "@suaveplan/cbor/cddl";
const ast = parseCddl(`
cwt = { iss: tstr, ? exp: int }
`);
```
## Usage: Advanced Example
```ts
import { parseCddl } from "@suaveplan/cbor/cddl";
const ast = parseCddl(`
attested-key = #6.18(cose-sign1)
cose-sign1 = [ protected: bstr, unprotected: { * any => any }, payload: bstr / nil, signature: bstr ]
protected = bstr .size 0..1024
pair<K, V> = [ K, V ]
`);
```
## API Reference
- `parseCddl(source: string): CddlAst`
Throws `CborError(CDDL_PARSE_FAILED)` with `{ line, col }` for: empty
source (no rules), missing `=`, unexpected token, non-integer range bound,
`#N` with N != 6.
## Implementation Notes
The parser is a hand-written recursive descent. Operator precedence
mirrors RFC 8610 §3:
- `type` (top): handles `/` choice
- `type1`: handles `..` / `...` ranges and control operators (`.size`,
`.regexp`, etc.); the `.size` case can take a range right-hand side
- `type2` (atom): primitives, references, literals, parenthesised groups,
arrays, maps, tagged items
Group choice (`//`) is implemented at the `[`/`{` body level — when the
parser encounters `//` between two sets of entries, it returns a
`{ kind: "choice", alternatives: [arrayA, arrayB] }` so the validator
can short-circuit on the first matching alternative.