/** * What joins two physical lines into one logical line: a leading `.` that * continues a call chain, a leading binary operator, and the A1 read-back that * decides whether the `//` starting a line is a comment or the floor division * a Python author meant. * * D115 §三 / D114 R1f: the continuation half of `lexer.ts`. */ import { type Advisory } from "../diagnostic.ts"; import { type Token } from "../token.ts"; /** Everything this half of the lexer asks of the scanner that hosts it, and nothing more. */ export interface LineContinuationHost { readonly advisories: Advisory[]; readonly bracketFragment: boolean; hasBracketOpenedOnLine(start: number): boolean; readonly index: number; isIdentifierPart(character: string): boolean; isIdentifierStart(character: string): boolean; lineStart(offset: number): number; readonly logicalLineIndent: number; peek(offset?: number): string; readonly text: string; readonly tokens: Token[]; } export declare class LineContinuation { private readonly host; constructor(host: LineContinuationHost); /** The width of a leading member step, or 0 where the line does not open with one. */ leadingDotWidth(): number; /** The binary operator starting this physical line, or null for a statement head. */ leadingBinaryOperator(): string | null; /** * Whether the leading continuation line at `width` joins the line above it. Two * conditions, and the file's own contract has always claimed both: * * - It is the *next* line. The backward walk used to skip an unbounded run of * `newline` tokens, so a chain joined a value that appeared any number of * blank lines and whole-line comments earlier — the case the header comment * says "never join accidentally" (D90, compiler-front-10). One `newline` * token is the line that ended the statement; a second is a blank or * comment line, and the statement ended there. * - It is indented past the statement it continues. The charter called the * deeper indentation canonical and nothing enforced it, so a column-0 * `.sorted()` dedented out of a function body and silently became part of * it. `logicalLineIndent` is the *statement's* indentation rather than the * previous physical line's, so every line of one chain answers to one rule. */ isChainContinuation(width: number): boolean; /** * D89 A1: `//` is VelarScript's only comment spelling, so a Python author's * floor division reads as a finished line followed by a comment and the * compiler has nothing to object to. `#` cannot take the comment role over: * of the branches the `#` dispatch reads (`readJavaScriptPrivateIdentifier`, * `readHexColor`, `readHashComment`), `readHexColor` carries bare * hexadecimal colors — a hot path in a language with `look:` — and a `#` * that opened a comment would swallow `#ff0000` and the rest of its line * instead of guiding it to the quoted spelling. With no comment spelling * left to give up, an advisory is the only remaining move. * * The trigger is narrow on both sides. D89 asks for a syntactically complete * expression or assignment ahead of the `//`, which here means three things: * the line carries code, every bracket *this physical line* opened is closed * before the comment (an unclosed one leaves the line unfinished, so * `print( // 2` is silent), and the last token can end a dividend. The * bracket test counts opens and closes on the line itself rather than reading * `nesting`: a bracket opened on an earlier line and closed on a later one * leaves the text before `//` complete, so `print(` / ` total // 2` / `)` * is exactly the mistake this advisory exists for and used to compile in * silence (D90). The comment's own text — with any `velar-allow` clause * removed, which is what `contentEnd` is for — must then be a bare arithmetic * body carrying a digit and no letter anywhere, so `// TODO`, * `// 2. then handle X`, a bare `//`, and a whole-line comment are all * silent. * * A bracket fragment is exempt because its lexer holds the fragment's text * rather than the module's: `lineStart` there answers with the fragment's own * beginning, and "the rest of this line is a comment" would be a claim about * an interpolation rather than about a physical line. * * No mechanical fix is registered: deciding that the comment really was a * divisor is the judgment D38 §48 keeps out of the fix registry. */ adviseFloorDivisionComment(start: number, bodyStart: number, contentEnd: number): void; /** * What Python's `//` would have divided: the primary expression the comment * follows, read back from the source so the advisory quotes the author's own * spelling. The walk stops at the first operator or keyword outside brackets, * because `//` binds as tightly as `*` — in `a + b // 2` the dividend is `b`, * and naming `a + b` would hand back a rewrite that changes the result. * * A leading unary sign belongs to the dividend. Python's `-7 // 2` is -4, so * quoting `7` and suggesting `(7 / 2).floor()` — which answers 3 — is the same * class of wrong rewrite the divisor side used to hand back. The sign is unary * exactly when nothing that could end an operand stands in front of it, which * keeps the binary reading in `a - 7 // 2`, where the dividend is still `7`. * * `target` is the name the value lands in, and only a plain `=` produces one: * a compound assignment reads its target as well as writing it, so calling it * the receiver would be a second claim this advisory has not checked. */ private dividendBeforeComment; } //# sourceMappingURL=continuation.d.ts.map