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);
}
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;
}
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;
}
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;
}
Aggregations