import type { Combinator, ParseContext, ParseFail } from '../types.ts'; /** * ADJACENCY assertions — `adjacent()` and `notAdjacent()`. * * These are the authoring surface for `docs/design/derived-tokenization.md` §4, * "Adjacency is a bit set at scan time". §4's fact is: *was there nothing between * the previous token and this one?* The trivia skip already answers it at every * sequence boundary and throws the answer away. `noTrivia` is today's POSITIVE * spelling of that fact and has no negative twin, so a production that needs * "these two are SEPARATED" has had to disable trivia and re-spell whitespace as a * regex — which re-implements the dialect's trivia table inside an expression * production, and drifts from it. * * The question is about the GAP, never about what a separator looks like: * * 1 - 2 the `-` is not adjacent to the `2` → subtraction * 1 -2 the `-` IS adjacent to the `2` → signed number in a list * * and a third case, `1`, a block comment, `-`, a block comment, `2`: not adjacent, * but the separation is a comment rather than whitespace. That case is why `kinds` * exists. css-values-4 §10.1 requires REAL whitespace * around `+`/`-` in `calc()`, because a comment vanishes at tokenisation: * `notAdjacent({ kinds: ['whitespace'] })` states that and nothing else. * * LOWERING. Both are marker tags, recognised by `sequence()` at term `i` and lowered * at that boundary into a test of the trivia scan the boundary already performs * (`scanEnd > cur`). That is deliberate on two counts: it costs nothing at all where * no assertion is written (no ctx field, no extra branch in the ordinary boundary), * and it sidesteps `sequence`'s trivia REWIND — a self-contained zero-width * combinator sitting at index `i` matches zero-width by construction, so the * `result.span.end > scanEnd` test would roll the gap it just asserted back out. * When derived tokenization lands, the same tag lowers to a `tight` bit test on the * token instead; the assertion an author writes does not change. */ export type AdjacencyDef = { tag: 'adjacency'; polarity: 'adjacent' | 'notAdjacent'; kinds?: readonly string[]; }; /** The adjacency spec of `p`, or null when `p` is an ordinary combinator. */ export declare function adjacencyOf(p: Combinator): AdjacencyDef | null; /** Failure label, matched byte-for-byte by the compiled path. */ export declare function adjacencyExpected(def: AdjacencyDef): string; /** * Evaluate one adjacency assertion at a sequence boundary. `cur` is the position * BEFORE the ambient trivia scan. No capture, no cursor movement, no ctx writes. */ export declare function holdsAdjacency(input: string, cur: number, ctx: ParseContext, def: AdjacencyDef): boolean; /** * The test itself, over the two things a def actually carries. * * Split from `holdsAdjacency` so the TABLE drivers can reach it: both decode a * polarity word and a const-pool slot out of the instruction stream and have no * `AdjacencyDef` object to hand — and manufacturing one per assertion, on a * boundary test that is otherwise allocation-free, would be an allocation the * interpreter does not pay. One implementation, three engines. */ export declare function adjacencyHolds(input: string, cur: number, ctx: ParseContext, negated: boolean, kinds: readonly string[] | undefined): boolean; export declare function adjacencyFail(pos: number, def: AdjacencyDef): ParseFail; /** * The error a marker in a position with no boundary raises — the same sentence * from every engine. * * The table drivers need it for the same reason the combinator does: an * assertion reached anywhere but a sequence term has no gap to test, and * silently answering "no trivia here" would make `notAdjacent()` a guaranteed * failure and `adjacent()` a no-op, both invisible. */ export declare function adjacencyMisuse(polarity: 'adjacent' | 'notAdjacent'): TypeError; /** * Zero-width assertion: the previous term and this position are ADJACENT — no * ambient trivia sat between them. * * The first-class spelling of what `noTrivia(...)` expresses today by clearing the * trivia table around a glued run. Use it when only the JOIN is significant and the * terms themselves are ordinary: * * sequence(number, adjacent(), unit) // `10px`, never `10 px` */ export declare function adjacent(): Combinator; /** * Zero-width assertion: the previous term and this position are NOT adjacent — * ambient trivia sat between them. * * `kinds` narrows it to trivia CATEGORIES declared by `classifiedTrivia({...})`, so * the assertion can demand a category that survives tokenisation: * * // css-values-4 10.1: `a + b` yes; a comment in place of the space, no. * sequence(operand, notAdjacent({ kinds: ['whitespace'] }), plusOrMinus, * notAdjacent({ kinds: ['whitespace'] }), operand) * * A `kinds` list is checked against the ACTIVE trivia table the first time the * assertion is reached (and at compile time for the compiled path). Unlabeled * trivia, or a kind name the table does not declare, is a hard `TypeError` — never * a silently-empty filter. */ export declare function notAdjacent(options?: { kinds?: readonly string[]; }): Combinator; //# sourceMappingURL=adjacency.d.ts.map