Files
suaveplan/packages/foundation/flow/cbor/src/cddl/ast.md
2026-05-27 23:47:53 +01:00

1.9 KiB

ast

Purpose

Typed AST shapes per RFC 8610 §3 — the contract between the parser and the validator (and any future code generator). Every CDDL syntactic construct lands as a discriminated-union node so consumers can pattern-match exhaustively.

Features

  • CddlAst — root: { rules: CddlRule[] }.
  • CddlRule — { name, generics, type }.
  • CddlType — discriminated union over: primitives, named refs (with generic args), literal values (text / byte / int / uint / bool / null / undefined), ranges, choice, arrays, maps, tagged items, control operators.
  • CddlGroupEntry — an array/map entry with occurrence, optional key, and a type.
  • CddlGroupKey — text / uint / int. (Typed keys are reserved for a future parser extension.)
  • CddlOccurrence — exact / optional / zero-or-more / one-or-more / range.
  • PrimitiveName + PRIMITIVE_NAMES — frozen set of every recognised prelude type from RFC 8610 §3.8.

Usage: Basic Example

import type { CddlAst, CddlRule } from "@suaveplan/cbor/cddl";

function ruleNames(ast: CddlAst): string[] {
  return ast.rules.map((r: CddlRule) => r.name);
}

Usage: Advanced Example

import type { CddlType } from "@suaveplan/cbor/cddl";

function isOptionalString(t: CddlType): boolean {
  return t.kind === "primitive" && t.name === "tstr";
}

API Reference

See the type definitions in ast.ts. The AST is intentionally pure data — no methods, no mutable state — so it round-trips through serialisation without surprises.

Implementation Notes

The AST is the public contract for downstream consumers (validators, code generators, schema-based fuzzers). Adding a new node kind requires updating both the parser (to produce it) and every walker (to consume it). The PRIMITIVE_NAMES set is exported so consumers writing their own walkers can recognise the prelude types without duplicating the literal union.