/** The java classes typically used to represent a parsed grammar AST; each inner class is a type of AST node. */
public class GrammarBuilder {
+ /**
+ * Create a grammar from a parse tree and binding resolver
+ *
+ * @param t a tree produced by parsing a grammar using the metagrammar
+ * @param s the name of the "start symbol"
+ * @param gbr a GrammarBindingResolver that resolves grammatical reductions into tree-node-heads
+ */
+ public static Union buildFromAST(Tree grammarAST, String startingNonterminal, File[] includes) {
+ return new GrammarBuilder(includes, "").buildGrammar(grammarAST, startingNonterminal);
+ }
+
public static Object illegalTag = ""; // this is the tag that should never appear in the non-dropped output FIXME
private final String prefix;
- private final String path;
+ private final File[] includes;
//public GrammarBuilder(String path) { this(path, ""); }
- public GrammarBuilder(String path, String prefix) {
+ public GrammarBuilder(File[] includes, String prefix) {
this.prefix = prefix;
- this.path = path;
+ this.includes = includes;
}
public Union buildGrammar(Tree t, String rootNonTerminal) {
if (head.equals("\n")) return "\n";
if (head.equals("\r")) return "\r";
if (head.equals("grammar.Grammar")) return walkChildren(t);
- if (head.equals("SubGrammar")) return Grammar.create(t.child(0), "s");
+ if (head.equals("SubGrammar")) return GrammarBuilder.buildFromAST(t.child(0), "s", includes);
if (head.equals("NonTerminal"))
return new NonTerminalNode((String)walk(t.child(0)),
(Seq[][])walkChildren(t.child(1)), false, null, false);
false,
false);
if (head.equals("#import")) {
- String fileName = path+(String)stringifyChildren(t.child(0));
- try {
- String newPrefix = (String)walk(t.child(1));
- if (newPrefix.length() > 0) newPrefix += ".";
- FileInputStream fis = new FileInputStream(fileName);
- Tree tr = new CharParser(MetaGrammar.newInstance()).parse(fis).expand1();
- return (GrammarNode)new GrammarBuilder(path, newPrefix).walk(tr);
- } catch (Exception e) {
- throw new RuntimeException("while parsing " + fileName, e);
+ String fileName = (String)stringifyChildren(t.child(0));
+ for(File f : includes) {
+ File file = new File(f.getAbsolutePath()+File.separatorChar+fileName);
+ if (!file.exists()) continue;
+ try {
+ String newPrefix = (String)walk(t.child(1));
+ if (newPrefix.length() > 0) newPrefix += ".";
+ FileInputStream fis = new FileInputStream(file);
+ Tree tr = new CharParser(MetaGrammar.newInstance()).parse(fis).expand1();
+ return (GrammarNode)new GrammarBuilder(includes, newPrefix).walk(tr);
+ } catch (Exception e) {
+ throw new RuntimeException("while parsing " + file, e);
+ }
}
+ throw new RuntimeException("unable to find #include file \""+fileName+"\"");
}
throw new RuntimeException("unknown head: " + head + "\n"+t);
}