Search in sources :

Example 1 with ParseTreeMatch

use of org.antlr.v4.runtime.tree.pattern.ParseTreeMatch in project antlr4 by antlr.

the class ParseTreePattern method findAll.

/**
	 * Find all nodes using XPath and then try to match those subtrees against
	 * this tree pattern.
	 *
	 * @param tree The {@link ParseTree} to match against this pattern.
	 * @param xpath An expression matching the nodes
	 *
	 * @return A collection of {@link ParseTreeMatch} objects describing the
	 * successful matches. Unsuccessful matches are omitted from the result,
	 * regardless of the reason for the failure.
	 */
public List<ParseTreeMatch> findAll(ParseTree tree, String xpath) {
    Collection<ParseTree> subtrees = XPath.findAll(tree, xpath, matcher.getParser());
    List<ParseTreeMatch> matches = new ArrayList<ParseTreeMatch>();
    for (ParseTree t : subtrees) {
        ParseTreeMatch match = match(t);
        if (match.succeeded()) {
            matches.add(match);
        }
    }
    return matches;
}
Also used : ArrayList(java.util.ArrayList) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 2 with ParseTreeMatch

use of org.antlr.v4.runtime.tree.pattern.ParseTreeMatch in project antlr4 by antlr.

the class ParseTreePatternMatcher method match.

/**
	 * 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.
	 */
public ParseTreeMatch match(ParseTree tree, ParseTreePattern pattern) {
    MultiMap<String, ParseTree> labels = new MultiMap<String, ParseTree>();
    ParseTree mismatchedNode = matchImpl(tree, pattern.getPatternTree(), labels);
    return new ParseTreeMatch(tree, pattern, labels, mismatchedNode);
}
Also used : MultiMap(org.antlr.v4.runtime.misc.MultiMap) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 3 with ParseTreeMatch

use of org.antlr.v4.runtime.tree.pattern.ParseTreeMatch in project antlr4 by antlr.

the class ParseTreePatternMatcher method matchImpl.

// ---- SUPPORT CODE ----
/**
	 * 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 ParseTree matchImpl(ParseTree tree, ParseTree patternTree, MultiMap<String, ParseTree> labels) {
    if (tree == null) {
        throw new IllegalArgumentException("tree cannot be null");
    }
    if (patternTree == null) {
        throw new IllegalArgumentException("patternTree cannot be null");
    }
    // x and <ID>, x and y, or x and x; or could be mismatched types
    if (tree instanceof TerminalNode && patternTree instanceof TerminalNode) {
        TerminalNode t1 = (TerminalNode) tree;
        TerminalNode t2 = (TerminalNode) patternTree;
        ParseTree mismatchedNode = null;
        // both are tokens and they have same type
        if (t1.getSymbol().getType() == t2.getSymbol().getType()) {
            if (t2.getSymbol() instanceof TokenTagToken) {
                // x and <ID>
                TokenTagToken tokenTagToken = (TokenTagToken) t2.getSymbol();
                // track label->list-of-nodes for both token name and label (if any)
                labels.map(tokenTagToken.getTokenName(), tree);
                if (tokenTagToken.getLabel() != null) {
                    labels.map(tokenTagToken.getLabel(), tree);
                }
            } else if (t1.getText().equals(t2.getText())) {
            // x and x
            } else {
                // x and y
                if (mismatchedNode == null) {
                    mismatchedNode = t1;
                }
            }
        } else {
            if (mismatchedNode == null) {
                mismatchedNode = t1;
            }
        }
        return mismatchedNode;
    }
    if (tree instanceof ParserRuleContext && patternTree instanceof ParserRuleContext) {
        ParserRuleContext r1 = (ParserRuleContext) tree;
        ParserRuleContext r2 = (ParserRuleContext) patternTree;
        ParseTree mismatchedNode = null;
        // (expr ...) and <expr>
        RuleTagToken ruleTagToken = getRuleTagToken(r2);
        if (ruleTagToken != null) {
            ParseTreeMatch m = null;
            if (r1.getRuleContext().getRuleIndex() == r2.getRuleContext().getRuleIndex()) {
                // track label->list-of-nodes for both rule name and label (if any)
                labels.map(ruleTagToken.getRuleName(), tree);
                if (ruleTagToken.getLabel() != null) {
                    labels.map(ruleTagToken.getLabel(), tree);
                }
            } else {
                if (mismatchedNode == null) {
                    mismatchedNode = r1;
                }
            }
            return mismatchedNode;
        }
        // (expr ...) and (expr ...)
        if (r1.getChildCount() != r2.getChildCount()) {
            if (mismatchedNode == null) {
                mismatchedNode = r1;
            }
            return mismatchedNode;
        }
        int n = r1.getChildCount();
        for (int i = 0; i < n; i++) {
            ParseTree childMatch = matchImpl(r1.getChild(i), patternTree.getChild(i), labels);
            if (childMatch != null) {
                return childMatch;
            }
        }
        return mismatchedNode;
    }
    // if nodes aren't both tokens or both rule nodes, can't match
    return tree;
}
Also used : ParserRuleContext(org.antlr.v4.runtime.ParserRuleContext) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 4 with ParseTreeMatch

use of org.antlr.v4.runtime.tree.pattern.ParseTreeMatch in project antlr4 by antlr.

the class TestParseTreeMatcher method testIDNodeWithLabelMatches.

@Test
public void testIDNodeWithLabelMatches() throws Exception {
    String grammar = "grammar X8;\n" + "s : ID ';' ;\n" + "ID : [a-z]+ ;\n" + "WS : [ \\r\\n\\t]+ -> skip ;\n";
    String input = "x ;";
    String pattern = "<id:ID>;";
    ParseTreeMatch m = checkPatternMatch(grammar, "s", input, pattern, "X8");
    assertEquals("{ID=[x], id=[x]}", m.getLabels().toString());
    assertNotNull(m.get("id"));
    assertNotNull(m.get("ID"));
    assertEquals("x", m.get("id").getText());
    assertEquals("x", m.get("ID").getText());
    assertEquals("[x]", m.getAll("id").toString());
    assertEquals("[x]", m.getAll("ID").toString());
    assertNull(m.get("undefined"));
    assertEquals("[]", m.getAll("undefined").toString());
}
Also used : ParseTreeMatch(org.antlr.v4.runtime.tree.pattern.ParseTreeMatch) Test(org.junit.Test)

Example 5 with ParseTreeMatch

use of org.antlr.v4.runtime.tree.pattern.ParseTreeMatch in project antlr4 by antlr.

the class TestParseTreeMatcher method testLabelGetsLastIDNode.

@Test
public void testLabelGetsLastIDNode() throws Exception {
    String grammar = "grammar X9;\n" + "s : ID ID ';' ;\n" + "ID : [a-z]+ ;\n" + "WS : [ \\r\\n\\t]+ -> skip ;\n";
    String input = "x y;";
    String pattern = "<id:ID> <id:ID>;";
    ParseTreeMatch m = checkPatternMatch(grammar, "s", input, pattern, "X9");
    assertEquals("{ID=[x, y], id=[x, y]}", m.getLabels().toString());
    assertNotNull(m.get("id"));
    assertNotNull(m.get("ID"));
    assertEquals("y", m.get("id").getText());
    assertEquals("y", m.get("ID").getText());
    assertEquals("[x, y]", m.getAll("id").toString());
    assertEquals("[x, y]", m.getAll("ID").toString());
    assertNull(m.get("undefined"));
    assertEquals("[]", m.getAll("undefined").toString());
}
Also used : ParseTreeMatch(org.antlr.v4.runtime.tree.pattern.ParseTreeMatch) Test(org.junit.Test)

Aggregations

ParseTree (org.antlr.v4.runtime.tree.ParseTree)4 ParseTreeMatch (org.antlr.v4.runtime.tree.pattern.ParseTreeMatch)4 Test (org.junit.Test)3 ArrayList (java.util.ArrayList)1 ParserRuleContext (org.antlr.v4.runtime.ParserRuleContext)1 MultiMap (org.antlr.v4.runtime.misc.MultiMap)1 TerminalNode (org.antlr.v4.runtime.tree.TerminalNode)1 ParseTreePattern (org.antlr.v4.runtime.tree.pattern.ParseTreePattern)1