/** * State module for TabScript transpiler. * Contains the State class that manages input/output during parsing. * * @module state * * > ⚠️ **Experimental API**: The plugin interface is still evolving. * > Expect breaking changes in minor releases until the API stabilizes. * * ## Public API for Plugins * * ### Input Navigation * - `read(...patterns)` - Consume token(s) without emitting. Returns undefined if no match. * - `peek(...patterns)` - Look ahead without consuming. * - `accept(...patterns)` - Consume and emit token(s). * - `acceptType(...patterns)` - Consume and emit only if not stripping types (`js=false`). * * ### Output * - `emit(text...)` - Emit output text. Numbers set source positions for source maps. * * ### State Management * - `snapshot()` - Create revertible state snapshot. * - `snapshot.revert()` - Revert both input and output state. * - `snapshot.revertOutput()` - Revert only output, returns discarded tokens. * - `snapshot.hasOutput()` - Check if any output has been emitted. * * ### Control Flow * - `must(result)` - Assert result is truthy or throw ParseError. * - `recoverErrors(func)` - Try/catch with error recovery support. * - `parseGroup(opts, itemFunc)` - Parse delimited/indented groups. * * ### Position Info * - `inLine` - Current input line number. * - `justAfterNewLine()` - True when at start of a new line. * - `lastNotSpace()` - Check if previous char is not a space. * - `hasMore()` - Check if more input remains. * * ### Configuration * - `options` - Readonly parser options. * - `errors` - Array of parse errors. */ import type { Options } from './tabscript.js'; /** * Creates a token matcher regex with a descriptive name for error messages. * Automatically adds the sticky (/y) flag if not present. * * This is the recommended way to create regex patterns for use with * `s.read()`, `s.accept()`, `s.peek()`, and related methods in plugins. * * @param regexp - The regular expression pattern to match tokens * @param name - A descriptive name shown in error messages (e.g., "identifier", "number") * @returns A new RegExp with the sticky flag and custom toString() */ export declare function pattern(regexp: RegExp, name: string): RegExp; /** * Error thrown when the TabScript parser encounters invalid syntax. * Contains position information (line, column, offset) for the error location. */ export declare class ParseError extends Error { offset: number; line: number; column: number; /** Input code that was skipped in an attempt to recover from the error. */ recoverSkip: string | undefined; constructor(offset: number, line: number, column: number, message: string); toString(): string; } /** * Options for parsing delimited or indented groups. * Used by `s.parseGroup()` to handle blocks like `{...}`, `[...]`, or indented blocks. */ export interface ParseGroupOpts { /** Opening delimiter in input (e.g., '{', '[', '|') */ open?: string; /** Closing delimiter in input (e.g., '}', ']', '|') */ close?: string; /** Item separator in input (e.g., ',', ';') */ next?: string; /** Opening delimiter in output (null to suppress) */ jsOpen?: string | null; /** Closing delimiter in output (null to suppress) */ jsClose?: string | null; /** Item separator in output (null to suppress) */ jsNext?: string | null; /** Allow implicit block via indentation (no explicit open/close) */ allowImplicit?: boolean; /** If false, don't emit separator after last item */ endNext?: false; } /** * Snapshot of parser state that can be used to revert changes. */ export interface Snapshot { /** Revert both input and output state to the snapshot point */ revert(): void; /** Revert only output state and returns the output tokens and mappings */ revertOutput(): (string | number)[]; /** Check if any output has been emitted since the snapshot */ hasOutput(): boolean; /** Get all source code that has been read since the snapshot */ getSource(): string; } export declare class State { private inData; readonly options: Options; private inPos; private indentLevel; private indentsPending; private inLastNewlinePos; private outTokens; private outTargetPos; private inPosLineCache; private inPosColCache; errors: ParseError[]; private matchOptions; constructor(inData: string, options: Options, startPos?: number); /** Current input line number */ get inLine(): number; /** Check if more input remains to be parsed */ hasMore(): boolean; /** * Clear the target position used for source mapping. * Called after header parsing to ensure next token gets correct position. */ clearTargetPos(): void; /** * Read token(s) from input, consuming them. Returns undefined if not matched. * RegExp arguments must have the /y (sticky) flag. */ read(what: RegExp | string): string | undefined; read(...whats: (RegExp | string)[]): string[] | undefined; /** * Peek at token(s) without consuming them. */ peek(...whats: (RegExp | string)[]): any; /** * Read and emit token(s). Returns undefined if not matched. */ accept(what: RegExp | string): string | undefined; accept(...whats: (RegExp | string)[]): string[] | undefined; /** * Read and emit token only if not stripping types. * Can also wrap a function call to strip its output when stripping types. */ acceptType(func: (...args: A) => T, ...args: A): T; acceptType(what: RegExp | string): string | undefined; acceptType(...whats: (RegExp | string)[]): string[] | undefined; /** * Emit output text. Automatically handles source mapping based on last read position. * Numbers are treated as explicit position markers. * `false` means the next arg should not have an automatic position emitted. * `true` means the next arg *should* have an automatic position emitted, but it should not be used for source mapping, and * the next token will get the same automatic position again. */ emit(...args: (string | boolean | number | undefined | null)[]): void; /** * Require a value to be truthy, throwing ParseError otherwise. */ must(result: T | undefined | false | (() => T | undefined | false)): T; /** * Create a snapshot of current state that can be reverted later. */ snapshot(): Snapshot; /** * Parse a group with optional delimiters and separators. */ parseGroup(opts: ParseGroupOpts, itemFunc: () => boolean): boolean; /** * Attempt to recover from errors during parsing. */ recoverErrors(func: () => any): any; /** * Check if we're at the start of a new line (for breaking operator processing). */ justAfterNewLine(): boolean; /** * Check if the character before current position is not a space. * Used to distinguish function calls foo(x) from spaced expressions foo (x). */ lastNotSpace(): boolean; /** * Check if the last emitted output ends with the given string. * Useful for conditionally emitting closing tokens. */ outputEndsWith(str: string): boolean; /** * Read a newline token (including handling indent changes). * This is public because the Main parser loop needs it. */ readNewline(): boolean; /** * Read an indent token. */ private readIndent; /** * Read a dedent token. */ private readDedent; /** * Convert an input position to line and column numbers. */ private getLineCol; /** * Format the output tokens into a final string with proper whitespace. */ getResult(): { code: string; errors: ParseError[]; map: { in: number[]; out: number[]; }; }; private debugLog; private joinTokens; }