Fix exponential complexity of recursive imports

This commit is contained in:
Sam Harwell 2014-09-25 21:02:13 -05:00
parent 9d6a6bd3a8
commit e4c193005e
2 changed files with 44 additions and 27 deletions

View File

@ -608,6 +608,8 @@ public class Tool {
return g; return g;
} }
private final Map<String, Grammar> importedGrammars = new HashMap<String, Grammar>();
/** /**
* Try current dir then dir of g then lib dir * Try current dir then dir of g then lib dir
* @param g * @param g
@ -615,27 +617,34 @@ public class Tool {
*/ */
public Grammar loadImportedGrammar(Grammar g, GrammarAST nameNode) throws IOException { public Grammar loadImportedGrammar(Grammar g, GrammarAST nameNode) throws IOException {
String name = nameNode.getText(); String name = nameNode.getText();
g.tool.log("grammar", "load " + name + " from " + g.fileName); Grammar imported = importedGrammars.get(name);
File importedFile = null; if (imported == null) {
for (String extension : ALL_GRAMMAR_EXTENSIONS) { g.tool.log("grammar", "load " + name + " from " + g.fileName);
importedFile = getImportedGrammarFile(g, name + extension); File importedFile = null;
if (importedFile != null) { for (String extension : ALL_GRAMMAR_EXTENSIONS) {
break; importedFile = getImportedGrammarFile(g, name + extension);
if (importedFile != null) {
break;
}
} }
if ( importedFile==null ) {
errMgr.grammarError(ErrorType.CANNOT_FIND_IMPORTED_GRAMMAR, g.fileName, nameNode.getToken(), name);
return null;
}
String absolutePath = importedFile.getAbsolutePath();
ANTLRFileStream in = new ANTLRFileStream(absolutePath, grammarEncoding);
GrammarRootAST root = parse(g.fileName, in);
if (root == null) {
return null;
}
imported = createGrammar(root);
imported.fileName = absolutePath;
importedGrammars.put(root.getGrammarName(), imported);
} }
if ( importedFile==null ) {
errMgr.grammarError(ErrorType.CANNOT_FIND_IMPORTED_GRAMMAR, g.fileName, nameNode.getToken(), name);
return null;
}
ANTLRFileStream in = new ANTLRFileStream(importedFile.getAbsolutePath(), grammarEncoding);
GrammarRootAST root = parse(g.fileName, in);
if ( root==null ) {
return null;
}
Grammar imported = createGrammar(root);
imported.fileName = importedFile.getAbsolutePath();
return imported; return imported;
} }

View File

@ -514,16 +514,24 @@ public class Grammar implements AttributeResolver {
* The grammars are in import tree preorder. Don't include ourselves * The grammars are in import tree preorder. Don't include ourselves
* in list as we're not a delegate of ourselves. * in list as we're not a delegate of ourselves.
*/ */
public List<Grammar> getAllImportedGrammars() { public List<Grammar> getAllImportedGrammars() {
if ( importedGrammars==null ) return null; if (importedGrammars == null) {
List<Grammar> delegates = new ArrayList<Grammar>(); return null;
for (Grammar d : importedGrammars) {
delegates.add(d);
List<Grammar> ds = d.getAllImportedGrammars();
if (ds != null) delegates.addAll(ds);
} }
return delegates;
} LinkedHashMap<String, Grammar> delegates = new LinkedHashMap<String, Grammar>();
for (Grammar d : importedGrammars) {
delegates.put(d.fileName, d);
List<Grammar> ds = d.getAllImportedGrammars();
if (ds != null) {
for (Grammar imported : ds) {
delegates.put(imported.fileName, imported);
}
}
}
return new ArrayList<Grammar>(delegates.values());
}
public List<Grammar> getImportedGrammars() { return importedGrammars; } public List<Grammar> getImportedGrammars() { return importedGrammars; }