Search in sources :

Example 1 with MultiMap

use of org.antlr.v4.runtime.misc.MultiMap 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 2 with MultiMap

use of org.antlr.v4.runtime.misc.MultiMap 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 3 with MultiMap

use of org.antlr.v4.runtime.misc.MultiMap in project antlr4 by antlr.

the class Antlr4Mojo method processGrammarFiles.

/**
     *
     * @param sourceDirectory
     * @exception InclusionScanException
     */
private List<List<String>> processGrammarFiles(List<String> args, Set<File> grammarFiles, GrammarDependencies dependencies, File sourceDirectory) throws InclusionScanException, IOException {
    // We don't want the plugin to run for every grammar, regardless of whether
    // it's changed since the last compilation. Check the mtime of the tokens vs
    // the grammar file mtime to determine whether we even need to execute.
    Set<File> grammarFilesToProcess = new HashSet<File>();
    for (File grammarFile : grammarFiles) {
        String tokensFileName = grammarFile.getName().split("\\.")[0] + ".tokens";
        File outputFile = new File(outputDirectory, tokensFileName);
        if ((!outputFile.exists()) || outputFile.lastModified() < grammarFile.lastModified() || dependencies.isDependencyChanged(grammarFile)) {
            grammarFilesToProcess.add(grammarFile);
        }
    }
    grammarFiles = grammarFilesToProcess;
    if (grammarFiles.isEmpty()) {
        getLog().info("No grammars to process");
        return Collections.emptyList();
    }
    MultiMap<String, File> grammarFileByFolder = new MultiMap<String, File>();
    // grammars to process.
    for (File grammarFile : grammarFiles) {
        if (!buildContext.hasDelta(grammarFile)) {
            continue;
        }
        buildContext.removeMessages(grammarFile);
        getLog().debug("Grammar file '" + grammarFile.getPath() + "' detected.");
        String relPathBase = MojoUtils.findSourceSubdir(sourceDirectory, grammarFile);
        String relPath = relPathBase + grammarFile.getName();
        getLog().debug("  ... relative path is: " + relPath);
        grammarFileByFolder.map(relPathBase, grammarFile);
    }
    List<List<String>> result = new ArrayList<List<String>>();
    for (Map.Entry<String, List<File>> entry : grammarFileByFolder.entrySet()) {
        List<String> folderArgs = new ArrayList<String>(args);
        if (!folderArgs.contains("-package") && !entry.getKey().isEmpty()) {
            folderArgs.add("-package");
            folderArgs.add(getPackageName(entry.getKey()));
        }
        for (File file : entry.getValue()) {
            folderArgs.add(entry.getKey() + file.getName());
        }
        result.add(folderArgs);
    }
    return result;
}
Also used : MultiMap(org.antlr.v4.runtime.misc.MultiMap) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) File(java.io.File) Map(java.util.Map) MultiMap(org.antlr.v4.runtime.misc.MultiMap) HashSet(java.util.HashSet)

Example 4 with MultiMap

use of org.antlr.v4.runtime.misc.MultiMap in project antlr4 by antlr.

the class ParseTreePatternMatcher method matches.

/** Does {@code pattern} matched as rule patternRuleIndex match tree? Pass in a
	 *  compiled pattern instead of a string representation of a tree pattern.
	 */
public boolean matches(ParseTree tree, ParseTreePattern pattern) {
    MultiMap<String, ParseTree> labels = new MultiMap<String, ParseTree>();
    ParseTree mismatchedNode = matchImpl(tree, pattern.getPatternTree(), labels);
    return mismatchedNode == null;
}
Also used : MultiMap(org.antlr.v4.runtime.misc.MultiMap) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Aggregations

MultiMap (org.antlr.v4.runtime.misc.MultiMap)3 ParseTree (org.antlr.v4.runtime.tree.ParseTree)3 File (java.io.File)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 ParserRuleContext (org.antlr.v4.runtime.ParserRuleContext)1 TerminalNode (org.antlr.v4.runtime.tree.TerminalNode)1