Files
zeekay a4debdba80 Read a .zap schema the way every other ZAP language reads it
C had no front end for the schema language at all. The compiler directory
holds a code generator plugin, which is handed a request by another tool
and never sees schema text, so a .zap file could not be read here in
either form -- indentation or braces.

zapgen reads it. Whitespace-significant source is rewritten into the brace
form BEFORE the parser, exactly as the Go reference does it: a near
identity that only adds the two tokens the brace grammar requires where
the indented form leaves them out. A file already in braces comes back
byte for byte, so one grammar reads both styles and neither is a dialect
of the other.

The identifier grammar is not restated. Its Unicode ranges are taken from
Go's own tables by gen/table, so a name this parser accepts is a name the
Go parser accepts, and a Go release that moves Unicode moves both.

The generated header gives each struct a view over the message bytes and
one reader per field at a fixed offset. Reading is in place and total: a
field past the end reads zero, a pointer into the head or out of the
message reads null. zap_view.h is the one place that says so.

Checked against the Go front end on every .zap in the estate plus 55
adversarial cases and 15000 random ones: the brace form each writes is
byte-identical, the layout each reads is field-for-field the same, and
they accept and refuse the same files for the same stated reason. A
message built by the Go runtime reads back through these bindings with
every field equal.
2026-09-15 11:32:12 -07:00

34 lines
1.3 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause-Eco */
/*
* desugar.h - the whitespace-significant form, written out in braces.
*
* Runs BEFORE the parser, so the proven brace grammar stays untouched. The
* transform is a near-identity: it only ADDS the two tokens the brace
* grammar requires where the whitespace form leaves them out.
*
* - A block header (`struct <Id>`) not already ended by '{' gains one,
* and a matching '}' is placed at the header's indent where the
* indented body ends.
* - A field written `Name Type` with no trailing '@N' gains `@<off>`,
* the running byte offset accumulated from the declared slot width of
* the fields before it in the same struct. An explicit '@N' is kept
* and resets the cursor to N + width.
*
* So a pure-brace file - every header ending in '{', every field carrying
* '@N' - comes back byte for byte unchanged, and the two styles may be
* mixed one top-level declaration at a time.
*/
#ifndef ZAPGEN_DESUGAR_H
#define ZAPGEN_DESUGAR_H
#include <stddef.h>
/* desugar writes the brace form of src into *out (malloc'd, NUL-terminated,
* *outlen bytes) and returns 0. On failure it returns -1 and writes the
* reason into err. */
int desugar(const char *src, size_t len, char **out, size_t *outlen,
char err[512]);
#endif