Class ParseTreePatternMatcher

java.lang.Object
org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher

public class ParseTreePatternMatcher extends Object
A tree pattern matching mechanism for ANTLR ParseTrees.

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 ParseTree with placeholders for the ID and expr subtree. Then the match(org.antlr.v4.runtime.tree.ParseTree, java.lang.String, int) routines can compare an actual 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 matches(org.antlr.v4.runtime.tree.ParseTree, java.lang.String, int) routines return true or false based upon a match for the tree rooted at the parameter sent in. The match(org.antlr.v4.runtime.tree.ParseTree, java.lang.String, int) routines return a 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 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 ParseTreePattern object.

See TestParseTreeMatcher for lots of examples. ParseTreePattern has two static helper methods: ParseTreePattern.findAll(org.antlr.v4.runtime.tree.ParseTree, java.lang.String) and ParseTreePattern.match(org.antlr.v4.runtime.tree.ParseTree) that are easy to use but not super efficient because they create new 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 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 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 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 setDelimiters(java.lang.String, java.lang.String, java.lang.String). You must escape both start and stop strings \< and \>.

  • Field Details

    • start

      protected String start
    • stop

      protected String stop
    • escape

      protected String escape
  • Constructor Details

    • ParseTreePatternMatcher

      public ParseTreePatternMatcher(Lexer lexer, Parser parser)
      Constructs a ParseTreePatternMatcher or from a Lexer and 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.
  • Method Details

    • setDelimiters

      public void setDelimiters(String start, String stop, String escapeLeft)
      Set the delimiters used for marking rule and token tags within concrete syntax used by the tree pattern parser.
      Parameters:
      start - The start delimiter.
      stop - The stop delimiter.
      escapeLeft - The escape sequence to use for escaping a start or stop delimiter.
      Throws:
      IllegalArgumentException - if start is null or empty.
      IllegalArgumentException - if stop is null or empty.
    • matches

      public boolean matches(ParseTree tree, String pattern, int patternRuleIndex)
      Does pattern matched as rule patternRuleIndex match tree?
    • matches

      public boolean matches(ParseTree tree, ParseTreePattern pattern)
      Does pattern matched as rule patternRuleIndex match tree? Pass in a compiled pattern instead of a string representation of a tree pattern.
    • match

      public ParseTreeMatch match(ParseTree tree, String pattern, int patternRuleIndex)
      Compare pattern matched as rule patternRuleIndex against tree and return a ParseTreeMatch object that contains the matched elements, or the node at which the match failed.
    • match

      public ParseTreeMatch match(ParseTree tree, ParseTreePattern pattern)
      Compare pattern matched against tree and return a 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.
    • compile

      public ParseTreePattern compile(String pattern, int patternRuleIndex)
      For repeated use of a tree pattern, compile it to a ParseTreePattern using this method.
    • getLexer

      public Lexer getLexer()
      Used to convert the tree pattern string into a series of tokens. The input stream is reset.
    • getParser

      public Parser getParser()
      Used to collect to the grammar file name, token names, rule names for used to parse the pattern into a parse tree.
    • matchImpl

      protected ParseTree matchImpl(ParseTree tree, ParseTree patternTree, MultiMap<String,ParseTree> labels)
      Recursively walk tree against patternTree, filling match.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.
    • getRuleTagToken

      protected RuleTagToken getRuleTagToken(ParseTree t)
      Is t (expr <expr>) subtree?
    • tokenize

      public List<? extends Token> tokenize(String pattern)
    • split

      public List<org.antlr.v4.runtime.tree.pattern.Chunk> split(String pattern)
      Split <ID> = <e:expr> ; into 4 chunks for tokenizing by tokenize(java.lang.String).