import type { Region } from './region.js'; import { TokenStore } from './tokens.js'; /** * One statement as the text writes it, terminated or not. * * Not an object in the model and carrying no schema meaning (FR-006): a statement whose type the * schema never heard of, or which carries twice the fields its type defines, is still a statement. * Deciding what any of it means is the reader's job, and the layer is what a reader positions * against. */ export interface Statement { /** The whole statement, from its first non-blank character through its terminator. */ readonly region: Region; /** Just the type name. Empty, at the offset one would have begun, when none was written. */ readonly typeName: Region; /** Type name text, exactly as written and not case-folded. */ readonly typeNameText: string; /** * Fields after the type name, in positional order, one region each. * * Index 0 is the first field after the type name, matching `RawObject.values`, which has already * had the type name shifted off. A field written empty still gets a region, an empty one * positioned where its value would have begun, so that positional indexing never shifts and a * blank slot in the middle of an extensible group can still be pointed at. * * The count is what was written rather than what the type defines. A statement carrying more or * fewer fields than its type is a finding, not a representation problem. */ readonly fields: readonly Region[]; /** True when no terminator was found, meaning the statement runs to end of input. */ readonly unterminated: boolean; } /** * Everything the text contains and where it was. * * The layer holds the text it was built from, which is what makes byte-identical reconstruction a * consequence rather than a feature: a reconstruction defined as concatenating slices of that text * returns the text by construction. What can actually break is the tiling, so that is what the * corpus test asserts and what {@link classify} makes observable. * * Nothing builds a layer implicitly (FR-005). `lex` and `parseIdf` read the same characters * through the same scan and construct none of this, so a caller who never names `scanIdf` pays * neither its time nor its memory. */ export interface SyntaxLayer { /** The text this layer was built from. Held so regions can be resolved. */ readonly text: string; /** Statements in source order. */ readonly statements: readonly Statement[]; /** Every meaningful token in source order, packed. Whitespace is not among them. */ readonly tokens: TokenStore; } /** * Scan IDF text into a syntax layer. * * Text and nothing else: no schema, because the layer records what the text says and never what it * means (FR-006). It never throws, for any input, and text that violates the grammar is * represented rather than stopped at (FR-004): an unterminated final statement runs to end of * input and says so, a statement written without a type name still tiles, and empty text produces * a layer with no statements and no tokens, which satisfies the tiling invariant vacuously. * * One linear pass over the shared scan, which is the same pass `lex` makes. The budget is a * quarter over a plain read of the same text; the work above the scan is a push per token and a * record per statement. */ export declare function scanIdf(text: string): SyntaxLayer; //# sourceMappingURL=layer.d.ts.map