UNPKG

antlr4ng

Version:

Alternative JavaScript/TypeScript runtime for ANTLR4

139 lines (138 loc) 5.82 kB
import { Token } from "./Token.js"; import { TokenStream } from "./TokenStream.js"; import { Interval } from "./misc/Interval.js"; /** * Useful for rewriting out a buffered input token stream after doing some * augmentation or other manipulations on it. * * You can insert stuff, replace, and delete chunks. Note that the operations * are done lazily--only if you convert the buffer to a {@link String} with * {@link TokenStream#getText()}. This is very efficient because you are not * moving data around all the time. As the buffer of tokens is converted to * strings, the {@link #getText()} method(s) scan the input token stream and * check to see if there is an operation at the current index. If so, the * operation is done and then normal {@link String} rendering continues on the * buffer. This is like having multiple Turing machine instruction streams * (programs) operating on a single input tape. :) * * This rewriter makes no modifications to the token stream. It does not ask the * stream to fill itself up nor does it advance the input cursor. The token * stream {@link TokenStream#index()} will return the same value before and * after any {@link #getText()} call. * * The rewriter only works on tokens that you have in the buffer and ignores the * current input cursor. If you are buffering tokens on-demand, calling * {@link #getText()} halfway through the input will only do rewrites for those * tokens in the first half of the file. * * Since the operations are done lazily at {@link #getText}-time, operations do * not screw up the token index values. That is, an insert operation at token * index `i` does not change the index values for tokens * `i`+1..n-1. * * Because operations never actually alter the buffer, you may always get the * original token stream back without undoing anything. Since the instructions * are queued up, you can easily simulate transactions and roll back any changes * if there is an error just by removing instructions. For example, * * ``` * CharStream input = new ANTLRFileStream("input"); * TLexer lex = new TLexer(input); * CommonTokenStream tokens = new CommonTokenStream(lex); * T parser = new T(tokens); * TokenStreamRewriter rewriter = new TokenStreamRewriter(tokens); * parser.startRule(); * ``` * * Then in the rules, you can execute (assuming rewriter is visible): * * ``` * Token t,u; * ... * rewriter.insertAfter(t, "text to put after t");} * rewriter.insertAfter(u, "text after u");} * System.out.println(rewriter.getText()); * ``` * * You can also have multiple "instruction streams" and get multiple rewrites * from a single pass over the input. Just name the instruction streams and use * that name again when printing the buffer. This could be useful for generating * a C file and also its header file--all from the same buffer: * * ``` * rewriter.insertAfter("pass1", t, "text to put after t");} * rewriter.insertAfter("pass2", u, "text after u");} * System.out.println(rewriter.getText("pass1")); * System.out.println(rewriter.getText("pass2")); * ``` * * If you don't use named rewrite streams, a "default" stream is used as the * first example shows. */ export declare class TokenStreamRewriter { static readonly DEFAULT_PROGRAM_NAME = "default"; static readonly PROGRAM_INIT_SIZE = 100; static readonly MIN_TOKEN_INDEX = 0; /** Our source stream */ protected readonly tokens: TokenStream; /** * You may have multiple, named streams of rewrite operations. * I'm calling these things "programs." * Maps String (name) -> rewrite (List) */ protected readonly programs: Map<string, RewriteOperation[]>; /** Map String (program name) -> Integer index */ protected readonly lastRewriteTokenIndexes: Map<string, number>; /** * @param tokens The token stream to modify */ constructor(tokens: TokenStream); getTokenStream(): TokenStream; /** * Insert the supplied text after the specified token (or token index) */ insertAfter(tokenOrIndex: Token | number, text: string, programName?: string): void; /** * Insert the supplied text before the specified token (or token index) */ insertBefore(tokenOrIndex: Token | number, text: unknown, programName?: string): void; /** * Replace the specified token with the supplied text */ replaceSingle(tokenOrIndex: Token | number, text: string, programName?: string): void; /** * Replace the specified range of tokens with the supplied text. */ replace(from: Token | number, to: Token | number, text: string | null, programName?: string): void; /** * Delete the specified range of tokens */ delete(from: Token | number, to?: Token | number | null, programName?: string): void; getProgram(name: string): RewriteOperation[]; initializeProgram(name: string): RewriteOperation[]; /** * @returns the text from the original tokens altered per the instructions given to this rewriter */ getText(intervalOrProgram?: Interval | string, programName?: string): string; /** * @returns a map from token index to operation */ protected reduceToSingleOperationPerIndex(rewrites: Array<RewriteOperation | null>): Map<number, RewriteOperation | null>; private catOpText; /** * Get all operations before an index of a particular kind */ private getKindOfOps; } declare class RewriteOperation { /** What index into rewrites List are we? */ instructionIndex: number; /** Token buffer index. */ index: number; text: unknown; tokens: TokenStream; constructor(tokens: TokenStream, index: number, instructionIndex: number, text: unknown); execute(_buf: string[]): number; toString(): string; } export {};