UNPKG

antlr4ng

Version:

Alternative JavaScript/TypeScript runtime for ANTLR4

153 lines (152 loc) 6.92 kB
import type { Lexer } from "../../Lexer.js"; import type { Parser } from "../../Parser.js"; import { Token } from "../../Token.js"; import { MultiMap } from "../../misc/MultiMap.js"; import type { ParseTree } from "../ParseTree.js"; import type { Chunk } from "./Chunk.js"; import { ParseTreeMatch } from "./ParseTreeMatch.js"; import { ParseTreePattern } from "./ParseTreePattern.js"; import { RuleTagToken } from "./RuleTagToken.js"; /** * A tree pattern matching mechanism for ANTLR {@link ParseTree}s. * * Patterns are strings of source input text with special tags representing * token or rule references such as: * * `<ID> = <expr>;` * * Given a pattern start rule such as `statement`, this object constructs * a {@link ParseTree} with placeholders for the `ID` and `expr` * subtree. Then the {@link #match} routines can compare an actual * {@link ParseTree} from a parse with this pattern. Tag `<ID>` matches * any `ID` token and tag `<expr>` references the result of the * `expr` rule (generally an instance of `ExprContext`. * * Pattern `x = 0;` is a similar pattern that matches the same pattern * except that it requires the identifier to be `x` and the expression to * be `0`. * * The {@link #matches} routines return `true` or `false` based * upon a match for the tree rooted at the parameter sent in. The * {@link #match} routines return a {@link ParseTreeMatch} object that * contains the parse tree, the parse tree pattern, and a map from tag name to * matched nodes (more below). A subtree that fails to match, returns with * {@link ParseTreeMatch#mismatchedNode} set to the first tree node that did not * match. * * For efficiency, you can compile a tree pattern in string form to a * {@link ParseTreePattern} object. * * See `TestParseTreeMatcher` for lots of examples. * {@link ParseTreePattern} has two static helper methods: * {@link ParseTreePattern.findAll} and {@link ParseTreePattern#match} that * are easy to use but not super efficient because they create new * {@link ParseTreePatternMatcher} objects each time and have to compile the * pattern in string form before using it. * * The lexer and parser that you pass into the {@link ParseTreePatternMatcher} * constructor are used to parse the pattern in string form. The lexer converts * the `<ID> = <expr>;` into a sequence of four tokens (assuming lexer * throws out whitespace or puts it on a hidden channel). Be aware that the * input stream is reset for the lexer (but not the parser; a * {@link ParserInterpreter} is created to parse the input.). Any user-defined * fields you have put into the lexer might get changed when this mechanism asks * it to scan the pattern string. * * Normally a parser does not accept token `<expr>` as a valid * `expr` but, from the parser passed in, we create a special version of * the underlying grammar representation (an {@link ATN}) that allows imaginary * tokens representing rules (`<expr>`) to match entire rules. We call * these *bypass alternatives*. * * Delimiters are `<` and `>`, with `\` as the escape string * by default, but you can set them to whatever you want using * {@link ParseTreePatternMatcher.setDelimiters}. You must escape both start and stop strings * `\<` and `\>`. */ export declare class ParseTreePatternMatcher { protected start: string; protected stop: string; protected escape: string; /** * This is the backing field for {@link #getLexer()}. */ private readonly lexer; /** * This is the backing field for {@link #getParser()}. */ private readonly parser; /** * Constructs a {@link ParseTreePatternMatcher} or from a {@link Lexer} and * {@link Parser} object. The lexer input stream is altered for tokenizing * the tree patterns. The parser is used as a convenient mechanism to get * the grammar name, plus token, rule names. */ constructor(lexer: Lexer | null, parser: Parser | null); /** * Set the delimiters used for marking rule and token tags within concrete * syntax used by the tree pattern parser. * * @param start The start delimiter. * @param stop The stop delimiter. * @param escapeLeft The escape sequence to use for escaping a start or stop delimiter. * * @throws Error if `start` is `null` or empty. * @throws Error if `stop` is `null` or empty. */ setDelimiters(start: string, stop: string, escapeLeft: string): void; /** * Does `pattern` matched as rule patternRuleIndex match tree? Pass in a * compiled pattern instead of a string representation of a tree pattern. */ matches(tree: ParseTree, pattern: ParseTreePattern): boolean; /** Does `pattern` matched as rule `patternRuleIndex` match `tree`? */ matches(tree: ParseTree, pattern: string, patternRuleIndex: number): boolean; /** * Compare `pattern` matched against `tree` and return a * {@link ParseTreeMatch} object that contains the matched elements, or the * node at which the match failed. Pass in a compiled pattern instead of a * string representation of a tree pattern. */ match(tree: ParseTree, pattern: ParseTreePattern): ParseTreeMatch; /** * Compare `pattern` matched as rule `patternRuleIndex` against * `tree` and return a {@link ParseTreeMatch} object that contains the * matched elements, or the node at which the match failed. */ match(tree: ParseTree, pattern: string, patternRuleIndex: number): ParseTreeMatch; /** * For repeated use of a tree pattern, compile it to a * {@link ParseTreePattern} using this method. */ compile(pattern: string, patternRuleIndex: number): ParseTreePattern; /** * Used to convert the tree pattern string into a series of tokens. The * input stream is reset. */ getLexer(): Lexer | null; /** * Used to collect to the grammar file name, token names, rule names for * used to parse the pattern into a parse tree. */ getParser(): Parser | null; tokenize(pattern: string): Token[]; /** * Split `<ID> = <e:expr> ;` into 4 chunks for tokenizing by {@link #tokenize}. */ split(pattern: string): Chunk[]; /** * Recursively walk `tree` against `patternTree`, filling * `match.`{@link ParseTreeMatch#labels labels}. * * @returns the first node encountered in `tree` which does not match * a corresponding node in `patternTree`, or `null` if the match * was successful. The specific node returned depends on the matching * algorithm used by the implementation, and may be overridden. */ protected matchImpl(tree: ParseTree, patternTree: ParseTree, labels: MultiMap<string, ParseTree>): ParseTree | undefined; /** * Is `t` `(expr <expr>)` subtree? */ protected getRuleTagToken(t: ParseTree): RuleTagToken | undefined; }