checkpoint
[sbp.git] / src / edu / berkeley / sbp / Sequence.java
index 8d6709d..5680d6c 100644 (file)
@@ -8,7 +8,7 @@ import java.lang.reflect.*;
 import java.lang.ref.*;
 
 /** <font color=green>juxtaposition; zero or more adjacent Elements; can specify a rewriting</font> */
-public abstract class Sequence extends Element implements Iterable<Element> {
+public abstract class Sequence implements Iterable<Element>, SequenceOrElement {
 
     protected final Element[] elements;
 
@@ -32,37 +32,43 @@ public abstract class Sequence extends Element implements Iterable<Element> {
         return ret;
     }
 
-    /** the empty sequence (matches the empty string) */
-    static final Sequence empty = new Sequence.Constant.Empty();
-    public static Sequence empty() { return empty; }
+    /** create an empty sequence (matches the empty string) */
+    public static Sequence create() { return new Sequence.Constant.Empty(); }
 
-    /** after matching the sequence, do not add anything to the output tree */
-    public static Sequence drop(Element[] e) { return new Constant.Drop(e); }
+    /** create a sequence of one element */
+    public static Sequence create(Element e) { return create(new Element[] { e }, 0); }
 
-    /** after matching the sequence, insert a constant into the output tree */
-    public static Sequence constant(Element[] e, Object o) { return new Constant(e, o); }
+    /** create a sequence which drops the result of all but one of its element */
+    public static Sequence create(Element[] e, int which) { return new Singleton(e, which); }
 
-    /** after matching the sequence, place the result of the <tt>idx</tt>th match in the output tree */
-    public static Sequence singleton(Element[] e, int idx) { return new Singleton(e, idx); }
-    public static Sequence singleton(Element e) { return singleton(new Element[] { e }, 0); }
+    /** create a sequence which always evaluates to a constant result  */
+    public static Sequence create(Element[] e, Object result) { return new Constant(e, result); }
 
     /**
-     *  after matching the sequence, create the specified output tree
-     *  @param tag   the tag for the output tree
-     *  @param e     the elements to match
-     *  @param drops only elements of <tt>e</tt> whose corresponding <tt>boolean</tt> in <tt>drops</tt>
-     *               is <i>false</i> will be included in the output tree
+     *  create a sequence (general form)
+     *  @param head   the head of the output tree
+     *  @param e      the elements to match
+     *  @param drop   only elements of <tt>e</tt> whose corresponding <tt>boolean</tt> in <tt>drops</tt>
+     *                is <i>false</i> will be included in the output tree
+     *  @param foster if true, all children of the last child (ie
+     *                grandchildren) are promoted to children of this
+     *                node; this is very useful for matching repetitions
      **/
-    public static Sequence rewritingSequence(Object tag, Element[] e, boolean[] drops) {
-        return new RewritingSequence(tag, e, drops); }
-
-    public static Sequence regionRewritingSequence(Functor<Input.Region,Object> tagfunctor, Element[] e, boolean[] drops) {
-        return new RegionRewritingSequence(tagfunctor, e, drops); }
+    public static Sequence create(Object head, Element[] e, boolean[] drop, boolean foster) {
+        return foster
+            ? new Unwrap(e, head, drop)
+            : new RewritingSequence(head, e, drop);
+    }
 
     ////////////////////////////////////////////////////////////////////////////////
 
+    /** return a new sequence identical to this one, but with a positive conjunct <tt>s</tt> */
     public Sequence and(Sequence s) { Sequence ret = dup(); ret.needs.add(s); return ret; }
-    public Sequence not(Sequence s) { Sequence ret = dup(); ret.hates.add(s); s.hated.add(ret); return ret; }
+
+    /** return a new sequence identical to this one, but with a negative conjunct <tt>s</tt> */
+    public Sequence andnot(Sequence s) { Sequence ret = dup(); ret.hates.add(s); s.hated.add(ret); return ret; }
+
+    /** return a new sequence identical to this one, but with a follow-set restricted to <tt>a</tt> */
     public Sequence followedBy(Atom a) { Sequence ret = dup(); ret.follow = a; return ret; }
 
     Iterable<Sequence> needs() { return needs; }
@@ -170,6 +176,14 @@ public abstract class Sequence extends Element implements Iterable<Element> {
             sb.append("-> ");
             sb.append(follow);
         }
+        for(Sequence s : needs) {
+            sb.append("& ");
+            sb.append(s);
+        }
+        for(Sequence s : hates) {
+            sb.append("&~ ");
+            sb.append(s);
+        }
         return sb;
     }
 
@@ -200,7 +214,6 @@ public abstract class Sequence extends Element implements Iterable<Element> {
         Sequence _clone() { return new Singleton(elements,idx); }
     }
 
-    public static Sequence unwrap(Element[] e, Object tag, boolean[] drops) { return new Unwrap(e, tag, drops); }
     static class Unwrap extends Sequence {
         private boolean[] drops;
         private final Object tag;