/*! * Copyright 2016 The ANTLR Project. All rights reserved. * Licensed under the BSD-3-Clause license. See LICENSE file in the project root for license information. */ import { Chunk } from "./Chunk"; import { Lexer } from '../../Lexer'; import { MultiMap } from "../../misc/MultiMap"; import { Parser } from '../../Parser'; import { ParseTree } from "../ParseTree"; import { ParseTreeMatch } from "./ParseTreeMatch"; import { ParseTreePattern } from "./ParseTreePattern"; import { RuleTagToken } from "./RuleTagToken"; import { Token } from "../../Token"; /** * 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:

* *

{@code = ;}

* *

Given a pattern start rule such as {@code statement}, this object constructs * a {@link ParseTree} with placeholders for the {@code ID} and {@code expr} * subtree. Then the {@link #match} routines can compare an actual * {@link ParseTree} from a parse with this pattern. Tag {@code } matches * any {@code ID} token and tag {@code } references the result of the * {@code expr} rule (generally an instance of {@code ExprContext}.

* *

Pattern {@code x = 0;} is a similar pattern that matches the same pattern * except that it requires the identifier to be {@code x} and the expression to * be {@code 0}.

* *

The {@link #matches} routines return {@code true} or {@code 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 {@code 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 {@code = ;} 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 {@code } as a valid * {@code 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 ({@code }) to match entire rules. We call * these bypass alternatives.

* *

Delimiters are {@code <} and {@code >}, with {@code \} as the escape string * by default, but you can set them to whatever you want using * {@link #setDelimiters}. You must escape both start and stop strings * {@code \<} and {@code \>}.

*/ export declare class ParseTreePatternMatcher { /** * This is the backing field for `lexer`. */ private _lexer; /** * This is the backing field for `parser`. */ private _parser; protected start: string; protected stop: string; protected escape: string; /** * Regular expression corresponding to escape, for global replace */ protected escapeRE: RegExp; /** * 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, parser: Parser); /** * 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. * * @exception IllegalArgumentException if {@code start} is {@code null} or empty. * @exception IllegalArgumentException if {@code stop} is {@code null} or empty. */ setDelimiters(start: string, stop: string, escapeLeft: string): void; /** Does {@code pattern} matched as rule {@code patternRuleIndex} match {@code tree}? */ matches(tree: ParseTree, pattern: string, patternRuleIndex: number): boolean; /** Does {@code 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; /** * Compare {@code pattern} matched as rule {@code patternRuleIndex} against * {@code 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; /** * Compare {@code pattern} matched against {@code 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; /** * 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. */ readonly lexer: Lexer; /** * Used to collect to the grammar file name, token names, rule names for * used to parse the pattern into a parse tree. */ readonly parser: Parser; /** * Recursively walk {@code tree} against {@code patternTree}, filling * {@code match.}{@link ParseTreeMatch#labels labels}. * * @return the first node encountered in {@code tree} which does not match * a corresponding node in {@code patternTree}, or {@code 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): ParseTree | undefined; /** Is {@code t} {@code (expr )} subtree? */ protected getRuleTagToken(t: ParseTree): RuleTagToken | undefined; tokenize(pattern: string): Token[]; /** Split {@code = ;} into 4 chunks for tokenizing by {@link #tokenize}. */ split(pattern: string): Chunk[]; } export declare namespace ParseTreePatternMatcher { class CannotInvokeStartRule extends Error { error: Error; constructor(error: Error); } class StartRuleDoesNotConsumeFullPattern extends Error { constructor(); } }