Central Docs
Catálogo Inicio

Gram Binary Intermediate Representation (GIR 1.0)

Module: gram.core.parser.c_driver
Format Version: 1.0 (GIR\0)
Status: Stable (Version 3.0.0)

Gram Binary IR (GIR) is a compact, relocatable, zero-copy binary serialization format for Abstract Syntax Trees produced by the native C parser. It allows compilers, linters, and analysis tools to stream, cache, and traverse parsed ASTs without paying the serialization or deserialization costs of JSON, XML, or protobufs.


1. Binary Layout Specification

A .gir binary buffer consists of three contiguous, 8-byte aligned sections:

┌─────────────────────────────────────────────────────────────┐
│ 1. Header (72 bytes)                                        │
│    Magic: "GIR\0" | Major: 1, Minor: 0                      │
│    Grammar ID, Source Hash, Source Size, Offsets, Counts    │
├─────────────────────────────────────────────────────────────┤
│ 2. Deduplicated UTF-8 String Pool                           │
│    Offsets Table (uint32_t[string_count + 1])               │
│    Contiguous Null-Terminated Strings (pool_bytes)          │
├─────────────────────────────────────────────────────────────┤
│ 3. Dense Node Table (40 bytes per node)                     │
│    Nodes 0..N (8-byte aligned)                              │
│    Node 0: Reserved NULL node                               │
│    Node 1..N: Preorder AST nodes                            │
└─────────────────────────────────────────────────────────────┘

2. Header Structure (GramIrHeader, 72 bytes)

typedef struct GramIrHeader {
    char     magic[4];                /* Always "GIR\0" (0x00524947) */
    uint16_t version_major;           /* Format major version (1) */
    uint16_t version_minor;           /* Format minor version (0) */
    uint32_t flags;                   /* Format flags (bit 0: little-endian) */
    uint32_t header_size;             /* Size of this header in bytes (72) */
    uint64_t grammar_id;              /* 64-bit SHA-256 fingerprint of the grammar & lexicon */
    uint64_t source_hash;             /* 64-bit FNV-1a hash of the source text */
    uint32_t source_size;             /* Original source size in bytes */
    uint32_t string_count;            /* Number of unique strings in the pool */
    uint32_t string_offsets_offset;   /* File offset of the string offsets table */
    uint32_t string_pool_offset;      /* File offset of the string byte buffer */
    uint32_t string_pool_bytes;       /* Total size of the string pool in bytes */
    uint32_t nodes_offset;            /* File offset of the node table (8-byte aligned) */
    uint32_t node_count;              /* Total node count (including dummy sentinel node 0) */
    uint32_t root_index;              /* Index of the root AST node in the node table */
    uint64_t total_size;              /* Total file size in bytes */
} GramIrHeader;

3. Node Structure (GramIrNode, 40 bytes)

Nodes use array indices rather than machine memory pointers, making the entire file relocatable across memory spaces and architectures:

typedef struct GramIrNode {
    uint16_t kind;           /* Node kind identifier (GramAstKind) */
    uint16_t flags;          /* Classification flags (see table below) */
    uint32_t symbol_id;      /* Index into string pool (rule name / lexeme) */
    uint32_t value;          /* Extra metadata payload (rule ID or token kind) */
    uint32_t src_start;      /* Byte offset in original UTF-8 source text */
    uint32_t src_length;     /* Byte length in original UTF-8 source text */
    uint32_t line;           /* 1-based line number */
    uint32_t column;         /* 0-based column number */
    uint32_t first_child;    /* Index of first child node (0 if none) */
    uint32_t next_sibling;   /* Index of next sibling node (0 if none) */
    uint32_t child_count;    /* Number of direct children */
} GramIrNode;

Node Classification Flags

Flag Constant Value Description
GRAM_IR_NODE_TERMINAL 0x01 Leaf terminal node (keyword, identifier, symbol, number, string).
GRAM_IR_NODE_RULE 0x02 Composite grammar rule node (ASTRef).
GRAM_IR_NODE_EXPR 0x04 Pratt expression node (EXPR_UNARY or EXPR_BINARY).
GRAM_IR_NODE_ARRAY 0x08 Sequence or delimited array (ARRAY).
GRAM_IR_NODE_RAW 0x10 Opaque raw code block captured via CaptureRaw (RAW).

4. C View API (GramIrView)

The GramIrView API allows reading and validating a .gir file without copying memory:

#include "gram_ir.h"

GramIrView view;
if (gram_ir_read_file("output.gir", &view) == GRAM_IR_OK) {
    if (gram_ir_view_matches_grammar(&view)) {
        printf("Valid GIR for grammar 0x%llx with %u nodes\n",
               (unsigned long long)view.header->grammar_id,
               view.header->node_count);
        
        /* Dump tree structure in human-readable indented format */
        gram_ir_dump(&view, stdout);
    }
    gram_ir_view_free(&view);
}

Structural Validation & Cycle Rejection

gram_ir_view_init() performs comprehensive validation before accepting a binary buffer:

  • Verifies magic number, versions, and total buffer size.
  • Ensures all offsets and sizes fit within buffer bounds and follow 8-byte alignment.
  • Performs iterative preorder validation to detect corrupted child links, out-of-range sibling indices, or cyclic loops.