mirror of
https://github.com/zap-proto/c.git
synced 2026-10-30 15:05:52 +00:00
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.
34 lines
1.3 KiB
C
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
|