checkpoint
[sbp.git] / src / edu / berkeley / sbp / meta / MetaGrammarBindings.java
index 0d9052c..196394a 100644 (file)
@@ -64,11 +64,18 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
 
     public abstract static class UnionNode extends ElementNode {
         public Seq[][] sequences;
+        public Atom toAtom(Context cx) {
+            Atom ret = null;
+            for(Seq[] ss : sequences)
+                for(Seq s : ss)
+                    ret = ret==null ? s.toAtom(cx) : infer(ret.union(s.toAtom(cx)));
+            return ret;
+        }
         public void build(Context cx, Union u, NonTerminalNode cnt) {
             HashSet<Sequence> bad2 = new HashSet<Sequence>();
             for(int i=0; i<sequences.length; i++) {
                 Seq[] group = sequences[i];
-                Union u2 = new Union();
+                Union u2 = new Union(null, false);
                 if (sequences.length==1) u2 = u;
                 for(int j=0; j<group.length; j++) {
                     group[j].build(cx, u2, false, cnt);
@@ -123,7 +130,7 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
             if (!rep) { super.build(cx, u, this); return; }
             HashSet<Sequence> bad2 = new HashSet<Sequence>();
 
-            Union urep = new Union();
+            Union urep = new Union(null, false);
             urep.add(Sequence.empty);
             if (sep != null)
                 urep.add(Sequence.singleton(new Element[] { cx.get(sep), u }, 1));
@@ -132,10 +139,10 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
 
             for(int i=0; i<sequences.length; i++) {
                 Seq[] group = sequences[i];
-                Union u2 = new Union();
+                Union u2 = new Union(null, false);
                 if (sequences.length==1) u2 = u;
                 for(int j=0; j<group.length; j++) {
-                    Union u3 = new Union();
+                    Union u3 = new Union(null, false);
                     group[j].build(cx, u3, false, this);
                     Sequence s = Sequence.unwrap(new Element[] { u3, urep },
                                                  cx.rm.repeatTag(),
@@ -164,7 +171,7 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
             this.sequences = sequences;
         }
         public Element build(Context cx, NonTerminalNode cnt) {
-            Union ret = new Union();
+            Union ret = new Union(null, false);
             build(cx, ret, cnt);
             return ret;
         }
@@ -192,8 +199,15 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         }
         public Seq(ElementNode e) { this(new ElementNode[] { e }); }
         public Seq(ElementNode[] elements) { this.elements = elements; }
+        public Atom toAtom(Context cx) {
+            if (elements.length != 1) throw new Error("FIXME");
+            return elements[0].toAtom(cx);
+        }
         public Seq tag(String tag) { this.tag = prefix+tag; return this; }
-        public Seq follow(ElementNode follow) { this.follow = follow; return this; }
+        public Seq follow(ElementNode follow) {
+            this.follow = follow;
+            return this;
+       }
         public Seq dup() {
             Seq ret = new Seq(elements);
             ret.and.addAll(and);
@@ -243,22 +257,22 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
                     for(int i=0; i<els.length; i++)
                         if (!drops[i])
                             if (idx==-1) idx = i;
-                            else throw new Error("multiple non-dropped elements in sequence: " + Sequence.drop(els,false));
+                            else throw new Error("multiple non-dropped elements in sequence: " + Sequence.drop(els, false));
                     if (idx != -1) ret = Sequence.singleton(els, idx);
                     else           ret = Sequence.drop(els, false);
                 }
             }
             if (this.follow != null)
-                ret.follow = infer(this.follow.build(cx, null));
+                ret.follow = this.follow.toAtom(cx);
             ret.lame = this.lame;
             return ret;
         }
     }
-    public static @bind.as("&")   Seq  and2(Seq s,        Seq a) { return s.and(a); }
-    public static @bind.as("&~")  Seq  andnot2(Seq s,     Seq a) { return s.andnot(a); }
-    public static @bind.as("->")  Seq  arrow(Seq s, ElementNode e)                { return s.follow(e); }
-    public static @bind.as("::")  Seq  tag(String tagname, Seq s)        { return s.tag(tagname); }
-    public static @bind.as("/")   Seq  slash(Seq s, ElementNode e)                { return s.separate(e); }
+    public static @bind.as("&")   Seq  and2(Seq s,        Seq a)   { return s.and(a); }
+    public static @bind.as("&~")  Seq  andnot2(Seq s,     Seq a)   { return s.andnot(a); }
+    public static @bind.as("->")  Seq  arrow(Seq s, ElementNode e) { return s.follow(e); }
+    public static @bind.as("::")  Seq  tag(String tagname, Seq s)  { return s.tag(tagname); }
+    public static @bind.as("/")   Seq  slash(Seq s, ElementNode e) { return s.separate(e); }
 
     public static Seq  seq(ElementNode[] elements)               { return new Seq(elements); }
     public static @bind.as("Elements")  Seq  seq2(ElementNode[] elements)               { return new Seq(elements); }
@@ -276,6 +290,9 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         public @bind.as("NonTerminalReference") NonTerminalReferenceNode(String nonTerminal) {
             this.nonTerminal = prefix + nonTerminal;
         }
+        public Atom toAtom(Context cx) {
+            return cx.grammar.get(nonTerminal).toAtom(cx);
+        }
         public Element build(Context cx, NonTerminalNode cnt) {
             if (!this.nonTerminal.startsWith(prefix)) nonTerminal = prefix + nonTerminal;
             Element ret = cx.get(nonTerminal);
@@ -285,33 +302,49 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
     }
 
     public static class Literal extends Constant {
-        public @bind Literal(@bind.arg String string) { super(CharRange.string(string)); }
+        private String string;
+        public @bind Literal(@bind.arg String string) {
+            super(CharAtom.string(string));
+            this.string = string;
+        }
         public boolean drop() { return true; }
+        public Atom toAtom(Context cx) {
+            if (string.length()!=1) return super.toAtom(cx);
+            edu.berkeley.sbp.util.Range.Set set = new edu.berkeley.sbp.util.Range.Set();
+            set.add(string.charAt(0), string.charAt(0));
+            return CharAtom.set(set);
+        }
     }
 
     public static                     class CharClass            extends ElementNode {
         Range[] ranges;
         public @bind.as("[") CharClass(Range[] ranges) { this.ranges = ranges; }
+        public Atom toAtom(Context cx) {
+            edu.berkeley.sbp.util.Range.Set set = new edu.berkeley.sbp.util.Range.Set();
+            for(Range r : ranges)
+                set.add(r.first, r.last);
+            return CharAtom.set(set);
+        }
         public Element build(Context cx, NonTerminalNode cnt) {
             edu.berkeley.sbp.util.Range.Set set = new edu.berkeley.sbp.util.Range.Set();
             for(Range r : ranges)
                 set.add(r.first, r.last);
-            return CharRange.set(set);
+            return CharAtom.set(set);
         }
     }
 
     public static @bind.as("{")           class XTree                 extends ElementNode {
         public @bind.arg Seq body;
         public Element build(Context cx, NonTerminalNode cnt) {
-            Union u = new Union();
+            Union u = new Union(null, false);
             Sequence s = body.build(cx, u, false, null);
-            Union u2 = new Union();
+            Union u2 = new Union(null, false);
             u2.add(Sequence.singleton(new Element[] {
-                CharRange.leftBrace,
+                CharAtom.leftBrace,
                 cx.get("ws"),
                 u,
                 cx.get("ws"),
-                CharRange.rightBrace
+                CharAtom.rightBrace
             }, 2));
             return u2;
         }
@@ -322,12 +355,16 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         public boolean zero, many, max;
         public Rep(ElementNode e, ElementNode sep, boolean zero, boolean many, boolean max) {
             this.e = e; this.sep = sep; this.zero = zero; this.many = many; this.max = max;}
+        public Atom toAtom(Context cx) {
+            if (sep != null) return super.toAtom(cx);
+            return e.toAtom(cx);
+        }
         public Element build(Context cx, NonTerminalNode cnt) {
             return (!max)
                 ? Sequence.repeat(e.build(cx, null), zero, many, sep==null ? null : sep.build(cx, null), cx.rm.repeatTag())
                 : sep==null
-                ? Sequence.repeatMaximal(infer(e.build(cx, null)), zero, many, cx.rm.repeatTag())
-                : Sequence.repeatMaximal(e.build(cx, null), zero, many, infer(sep.build(cx, null)), cx.rm.repeatTag());
+                ? Sequence.repeatMaximal(e.toAtom(cx), zero, many, cx.rm.repeatTag())
+                : Sequence.repeatMaximal(e.build(cx, null), zero, many, sep.toAtom(cx), cx.rm.repeatTag());
         }
     }
 
@@ -355,16 +392,19 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
 
     public static @bind.as("^")   ElementNode caret(final String s) {
         final String thePrefix = prefix;
-        return new Constant(CharRange.string(s)) {
+        return new Constant(CharAtom.string(s)) {
                 public String getOwnerTag() { return thePrefix+s; }
                 public boolean drop() { return true; }
             };
     }
 
     public static @bind.as("~")   ElementNode tilde(final ElementNode e) {
-        return new PostProcess(e) {
-                public Element postProcess(Element e) {
-                    return infer((Topology<Character>)Atom.toAtom(e).complement().minus(CharRange.braces));
+        return new ElementNodeWrapper(e) {
+                public Atom toAtom(Context cx) {
+                    return infer((Topology<Character>)e.toAtom(cx).complement().minus(CharAtom.braces));
+                }
+                public Element build(Context cx, NonTerminalNode cnt) {
+                    return infer((Topology<Character>)e.toAtom(cx).complement().minus(CharAtom.braces));
                 } }; }
 
     public static @bind.as("Word")        String word(String s) { return s; }
@@ -374,8 +414,8 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
     public static @bind.as("\n")          String retur() { return "\n"; }
     public static @bind.as("\r")          String lf() { return "\r"; }
 
-    static Atom infer(Element e)  { return infer((Topology<Character>)Atom.toAtom(e)); }
-    static Atom infer(Topology<Character> t) { return new CharRange(new CharTopology(t)); }
+    //static Atom infer(Element e)  { return infer((Topology<Character>)Atom.toAtom(e)); }
+    static Atom infer(Topology<Character> t) { return new CharAtom(new CharTopology(t)); }
 
     public static class Context {
         public HashMap<String,Union> map = new HashMap<String,Union>();
@@ -425,6 +465,7 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         public String getLabel() { return null; }
         public String getOwnerTag() { return null; }
         public boolean drop() { return false; }
+        public Atom toAtom(Context cx) { throw new Error("can't convert a " + this.getClass().getName() + " to an atom"); }
         public abstract Element build(Context cx, NonTerminalNode cnt);
     }
 
@@ -434,6 +475,7 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         public String getLabel() { return _e.getLabel(); }
         public String getOwnerTag() { return _e.getOwnerTag(); }
         public boolean drop() { return _e.drop(); }
+        public Atom toAtom(Context cx) { return _e.toAtom(cx); }
         public Element build(Context cx, NonTerminalNode cnt) { return _e.build(cx, cnt); }
     }
 
@@ -441,10 +483,13 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         Element constant;
         public Constant(Element constant) { this.constant = constant; }
         public Element build(Context cx, NonTerminalNode cnt) { return constant; }
+        public Atom toAtom(Context cx) {
+            if (constant instanceof Atom) return ((Atom)constant);
+            return super.toAtom(cx);
+        }
     }
 
     public abstract static class PostProcess extends ElementNodeWrapper {
-        ElementNode e;
         public PostProcess(ElementNode e) { super(e); }
         public Element build(Context cx, NonTerminalNode cnt) { return postProcess(_e.build(cx, cnt)); }
         public abstract Element postProcess(Element e);
@@ -460,4 +505,11 @@ public class MetaGrammarBindings extends AnnotationGrammarBindings {
         public Label(String label, ElementNode e) { super(e); this.label = label; }
         public String getLabel() { return label; }
     }
+
+    static class Invert extends Atom {
+        private final Atom a;
+        public Invert(Atom a) { this.a = a; }
+        public Topology top() { return a.complement(); }
+        public String toString() { return "~"+a; }
+    }
 }