reorganize GrammarAST hierarchy to make clear the distinction between ElementNodes...
authoradam <adam@megacz.com>
Tue, 4 Mar 2008 05:26:36 +0000 (00:26 -0500)
committeradam <adam@megacz.com>
Tue, 4 Mar 2008 05:26:36 +0000 (00:26 -0500)
darcs-hash:20080304052636-5007d-f2c2f6c593e2188d37d1943686c0e8925ca9f7ae.gz

src/edu/berkeley/sbp/meta/GrammarAST.java
src/edu/berkeley/sbp/util/StringUtil.java

index 586d519..1c1ef3d 100644 (file)
@@ -214,96 +214,22 @@ public class GrammarAST {
         }
     }
 
-    /** a node in the AST which is resolved into an Element */
-    private abstract class ElementNode {
-        public boolean isLifted() { return false; }
-        public boolean isDropped(Context cx) { return false; }
-        public Atom toAtom(Context cx) { throw new Error("can't convert a " + this.getClass().getName() + " to an atom: " + this); }
-        public abstract Element build(Context cx, NonTerminalNode cnt, boolean dropall);
-    }
-
-    /** a union, produced by a ( .. | .. | .. ) construct */
-    private class UnionNode extends ElementNode {
-
-        /** each component of a union is a sequence */
-        public Seq[][] sequences;
-
-        /** if the union is a NonTerminal specified as Foo*=..., this is true */
-        public boolean rep;
-
-        /** if the union is a NonTerminal specified as Foo* /ws=..., then this is "ws" */
-        public String  sep = null;
-
-        public UnionNode(Seq seq) { this(new Seq[][] { new Seq[] { seq } }); }
-        public UnionNode(Seq[][] sequences) { this(sequences, false, null); }
-        public UnionNode(Seq[][] sequences, boolean rep, String sep) {
-            this.sequences = sequences;
-            this.rep = rep;
-            this.sep = sep;
-        }
-        public boolean isDropped(Context cx) {
-            for(Seq[] seqs : sequences)
-                for(Seq seq : seqs)
-                    if (!seq.isDropped(cx))
-                        return false;
-            return true;
-        }
-        public Atom toAtom(Context cx) {
-            Atom ret = null;
-            for(Seq[] ss : sequences)
-                for(Seq s : ss)
-                    ret = ret==null ? s.toAtom(cx) : (Atom)ret.union(s.toAtom(cx));
-            return ret;
-        }
-        public Element build(Context cx, NonTerminalNode cnt, boolean dropall) {
-            return buildIntoPreallocatedUnion(cx, cnt, dropall, new Union(null, false)); }
-        public Element buildIntoPreallocatedUnion(Context cx, NonTerminalNode cnt, boolean dropall, Union u) {
-            Union urep = null;
-            if (rep) {
-                urep = new Union(null, false);
-                urep.add(Sequence.create(cnt.name, new Element[0]));
-                urep.add(sep==null
-                         ? Sequence.create(new Element[] { u }, 0)
-                         : Sequence.create(new Element[] { cx.get(sep), u }, 1));
-            }
-            HashSet<Sequence> bad2 = new HashSet<Sequence>();
-            for(int i=0; i<sequences.length; i++) {
-                Seq[] group = sequences[i];
-                Union u2 = new Union(null, false);
-                if (sequences.length==1) u2 = u;
-                for(int j=0; j<group.length; j++)
-                    if (!rep)
-                        group[j].build(cx, u2, cnt, dropall);
-                    else {
-                        Union u3 = new Union(null, false);
-                        group[j].build(cx, u3, cnt, dropall);
-                        Sequence s = Sequence.create(cnt.name,
-                                                     new Element[] { u3, urep },
-                                                     new boolean[] { false, false },
-                                                     new boolean[] { false, true});
-                        u2.add(s);
-                    }
-                if (sequences.length==1) break;
-                Sequence seq = Sequence.create(u2);
-                for(Sequence s : bad2) seq = seq.andnot(s);
-                u.add(seq);
-                bad2.add(Sequence.create(u2));
-            }
-            return u;
-        }
-    }
-
     /** a NonTerminal is always a union at the top level */
-    private class NonTerminalNode extends UnionNode {
-        public boolean alwaysDrop;
-        public String  name = null;
-        public boolean isDropped(Context cx) { return alwaysDrop; }
+    private class NonTerminalNode {
+        public final boolean alwaysDrop;
+        public final String  name;
+        public final ElementNode elementNode;
+        public final UnionNode unionNode;
         public NonTerminalNode(String name, Seq[][] sequences, boolean rep, String sep, boolean alwaysDrop) {
-            super(sequences, rep, sep==null?null:(prefix + sep));
             this.name = prefix + name;
             this.alwaysDrop = alwaysDrop;
+            this.unionNode = new UnionNode(sequences, rep, sep==null?null:(prefix + sep));
+            this.elementNode = alwaysDrop ? new DropNode(unionNode) : unionNode;
         }
+        public boolean isDropped(Context cx) { return alwaysDrop; }
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) { return cx.get(name); }
+        public ElementNode getElementNode() { return elementNode; }
+        public UnionNode   getUnionNode() { return unionNode; }
     }
 
     /** a sequence */
@@ -429,6 +355,90 @@ public class GrammarAST {
         }
     }
 
+    /** a node in the AST which is resolved into an Element */
+    private abstract class ElementNode {
+        /** the field name to be used when synthesizing AST classes; null if none suggested */
+        public String getFieldName() { return null; }
+        public boolean isLifted() { return false; }
+        public boolean isDropped(Context cx) { return false; }
+        public Atom toAtom(Context cx) { throw new Error("can't convert a " + this.getClass().getName() + " to an atom: " + this); }
+        public abstract Element build(Context cx, NonTerminalNode cnt, boolean dropall);
+    }
+
+    /** a union, produced by a ( .. | .. | .. ) construct */
+    private class UnionNode extends ElementNode {
+
+        /** each component of a union is a sequence */
+        public Seq[][] sequences;
+
+        /** if the union is a NonTerminal specified as Foo*=..., this is true */
+        public boolean rep;
+
+        /** if the union is a NonTerminal specified as Foo* /ws=..., then this is "ws" */
+        public String  sep = null;
+
+        public UnionNode(Seq seq) { this(new Seq[][] { new Seq[] { seq } }); }
+        public UnionNode(Seq[][] sequences) { this(sequences, false, null); }
+        public UnionNode(Seq[][] sequences, boolean rep, String sep) {
+            this.sequences = sequences;
+            this.rep = rep;
+            this.sep = sep;
+        }
+        public String getFieldName() { return null; }
+        public boolean isLifted() { return false; }
+        public boolean isDropped(Context cx) {
+            for(Seq[] seqs : sequences)
+                for(Seq seq : seqs)
+                    if (!seq.isDropped(cx))
+                        return false;
+            return true;
+        }
+        public Atom toAtom(Context cx) {
+            Atom ret = null;
+            for(Seq[] ss : sequences)
+                for(Seq s : ss)
+                    ret = ret==null ? s.toAtom(cx) : (Atom)ret.union(s.toAtom(cx));
+            return ret;
+        }
+
+        public Element build(Context cx, NonTerminalNode cnt, boolean dropall) {
+            return buildIntoPreallocatedUnion(cx, cnt, dropall, new Union(null, false)); }
+        public Element buildIntoPreallocatedUnion(Context cx, NonTerminalNode cnt, boolean dropall, Union u) {
+            Union urep = null;
+            if (rep) {
+                urep = new Union(null, false);
+                urep.add(Sequence.create(cnt.name, new Element[0]));
+                urep.add(sep==null
+                         ? Sequence.create(new Element[] { u }, 0)
+                         : Sequence.create(new Element[] { cx.get(sep), u }, 1));
+            }
+            HashSet<Sequence> bad2 = new HashSet<Sequence>();
+            for(int i=0; i<sequences.length; i++) {
+                Seq[] group = sequences[i];
+                Union u2 = new Union(null, false);
+                if (sequences.length==1) u2 = u;
+                for(int j=0; j<group.length; j++)
+                    if (!rep)
+                        group[j].build(cx, u2, cnt, dropall);
+                    else {
+                        Union u3 = new Union(null, false);
+                        group[j].build(cx, u3, cnt, dropall);
+                        Sequence s = Sequence.create(cnt.name,
+                                                     new Element[] { u3, urep },
+                                                     new boolean[] { false, false },
+                                                     new boolean[] { false, true});
+                        u2.add(s);
+                    }
+                if (sequences.length==1) break;
+                Sequence seq = Sequence.create(u2);
+                for(Sequence s : bad2) seq = seq.andnot(s);
+                u.add(seq);
+                bad2.add(Sequence.create(u2));
+            }
+            return u;
+        }
+    }
+
     /** reference to a NonTerminal by name */
     private class ReferenceNode extends ElementNode {
         public String nonTerminal;
@@ -445,7 +455,7 @@ public class GrammarAST {
             return ret;
         }
         public Atom toAtom(Context cx) {
-            ElementNode ret = cx.grammar.get(nonTerminal);
+            ElementNode ret = cx.grammar.get(nonTerminal).getElementNode();
             if (ret == null) throw new RuntimeException("unknown nonterminal \""+nonTerminal+"\"");
             return ret.toAtom(cx);
         }
@@ -580,7 +590,7 @@ public class GrammarAST {
             } else {
                 ret = new Union(name, false);
                 map.put(name, ret);
-                nt.buildIntoPreallocatedUnion(this, nt, nt.isDropped(this), ret);
+                nt.getUnionNode().buildIntoPreallocatedUnion(this, nt, nt.isDropped(this), ret);
             }
             return ret;
         }
index ee6d486..a5a5d9a 100644 (file)
@@ -91,4 +91,9 @@ public class StringUtil {
         }
         return ret.toString();
     }
+
+    public static String uncapitalize(String s) {
+        if (s==null) return null;
+        return (""+s.charAt(0)).toUpperCase()+s.substring(1);
+    }
 }