cleanups, reorg, and commenting
[sbp.git] / src / edu / berkeley / sbp / meta / GrammarBuilder.java
index 2b1d765..3651be3 100644 (file)
@@ -31,15 +31,26 @@ import java.io.*;
 /** 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) {
@@ -117,7 +128,7 @@ public class GrammarBuilder {
         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);
@@ -137,16 +148,21 @@ public class GrammarBuilder {
                                                 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);
     }