clean up metagrammar handling of drop and question-mark
authoradam <adam@megacz.com>
Wed, 28 Mar 2007 00:28:50 +0000 (20:28 -0400)
committeradam <adam@megacz.com>
Wed, 28 Mar 2007 00:28:50 +0000 (20:28 -0400)
darcs-hash:20070328002850-5007d-fe9e50e8faf3831371b2dc77b062876d200c4ee1.gz

src/edu/berkeley/sbp/meta/GrammarBuilder.java
src/edu/berkeley/sbp/meta/Repeat.java
tests/regression.tc

index 3651be3..e6e06ad 100644 (file)
@@ -264,7 +264,7 @@ public class GrammarBuilder {
     public class NonTerminalNode extends UnionNode {
         public boolean alwaysDrop;
         public String  name = null;
-        public boolean drop() { return alwaysDrop; }
+        public boolean drop(Context cx) { return alwaysDrop; }
         public NonTerminalNode(String name, Seq[][] sequences, boolean rep, String sep, boolean alwaysDrop) {
             super(sequences, rep, sep==null?null:(prefix + sep));
             this.name = prefix + name;
@@ -275,7 +275,7 @@ public class GrammarBuilder {
 
     public class Seq {
         public boolean alwaysDrop = false;
-        public boolean drop() { return alwaysDrop; }
+        public boolean drop(Context cx) { return alwaysDrop; }
         HashSet<Seq> and = new HashSet<Seq>();
         HashSet<Seq> not = new HashSet<Seq>();
         ElementNode[] elements;
@@ -326,13 +326,10 @@ public class GrammarBuilder {
         public Sequence build0(Context cx, NonTerminalNode cnt, boolean dropall) {
             boolean[] drops = new boolean[elements.length];
             Element[] els = new Element[elements.length];
-            dropall |= drop();
+            dropall |= drop(cx);
             for(int i=0; i<elements.length; i++) {
                 if (dropall) drops[i] = true;
-                else         drops[i] = elements[i].drop();
-                if (elements[i] instanceof ReferenceNode)
-                    if (((ReferenceNode)elements[i]).resolve(cx).drop())
-                        drops[i] = true;
+                else         drops[i] = elements[i].drop(cx);
                 if (elements[i].getOwnerTag() != null)
                     tag = elements[i].getOwnerTag();
             }
@@ -374,6 +371,7 @@ public class GrammarBuilder {
         public NonTerminalNode resolve(Context cx) { return cx.grammar.get(nonTerminal); }
         public ReferenceNode(String nonTerminal) { this.nonTerminal = prefix + nonTerminal; }
         public Atom toAtom(Context cx) { return cx.grammar.get(nonTerminal).toAtom(cx); }
+        public boolean drop(Context cx) { return resolve(cx).drop(cx); }
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) {
             if (!this.nonTerminal.startsWith(prefix)) nonTerminal = prefix + nonTerminal;
             Element ret = cx.get(nonTerminal);
@@ -393,7 +391,7 @@ public class GrammarBuilder {
         }
         public String getOwnerTag() { return caret ? thePrefix+string : super.getOwnerTag(); }
         public String toString() { return "\""+string+"\""; }
-        public boolean drop() { return true; }
+        public boolean drop(Context cx) { 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();
@@ -423,16 +421,23 @@ public class GrammarBuilder {
 
     public class RepeatNode extends ElementNode {
         public ElementNode e, sep;
-        public boolean zero, many, max;
+        public final boolean zero, many, max;
         public RepeatNode(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;}
+            this.e = e; this.sep = sep; this.zero = zero; this.many = many; this.max = max;
+        }
         public Atom toAtom(Context cx) { return sep==null ? e.toAtom(cx) : super.toAtom(cx); }
+        public boolean drop(Context cx) { return e.drop(cx); }
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) {
-            if (!dropall && !drop() && !e.drop())
-                throw new Error("you need a tag on this repetition: " + build(cx, cnt, dropall, ""));
-            return build(cx, cnt, dropall, illegalTag);
+            Element ret = build(cx, cnt, dropall, illegalTag);
+            String must = "must be tagged unless they appear within a dropped expression or their contents are dropped: ";
+            if (!dropall && !drop(cx) && !e.drop(cx))
+                if (!many)      throw new RuntimeException("options (?) " + must + ret);
+                else if (zero)  throw new RuntimeException("zero-or-more repetitions (*) " + must + ret);
+                else            throw new RuntimeException("one-or-more repetitions (+) " + must + ret);
+            return ret;
         }
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall, Object repeatTag) {
+            if (!many) System.out.println("tag is: " + repeatTag);
             return (!max)
                 ? Repeat.repeat(e.build(cx, null, dropall), zero, many, sep==null ? null : sep.build(cx, null, dropall), repeatTag)
                 : sep==null
@@ -443,7 +448,7 @@ public class GrammarBuilder {
 
     public abstract class ElementNode {
         public String getOwnerTag() { return null; }
-        public boolean drop() { return false; }
+        public boolean drop(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);
     }
@@ -452,7 +457,7 @@ public class GrammarBuilder {
         protected ElementNode _e;
         public ElementNodeWrapper(ElementNode e) { this._e = e; }
         public String getOwnerTag() { return _e.getOwnerTag(); }
-        public boolean drop() { return _e.drop(); }
+        public boolean drop(Context cx) { return _e.drop(cx); }
         public Atom toAtom(Context cx) { return _e.toAtom(cx); }
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) { return _e.build(cx, cnt, dropall); }
     }
@@ -465,7 +470,7 @@ public class GrammarBuilder {
 
     public class DropNode extends ElementNodeWrapper {
         public DropNode(ElementNode e) { super(e); }
-        public boolean drop() { return true; }
+        public boolean drop(Context cx) { return true; }
     }
 
     public    Seq  and2(Seq s,        Seq a)   { a.alwaysDrop = true;  return s.and(a); }
@@ -482,7 +487,7 @@ public class GrammarBuilder {
     public    ElementNode star(final ElementNode e)                            { return new RepeatNode(e, null, true,  true, false); }
     public  ElementNode starmaxfollow(final ElementNode e, final ElementNode sep)     { return new RepeatNode(e, sep,  true,  true, true); }
     public   ElementNode starfollow(final ElementNode e, final ElementNode sep)        { return new RepeatNode(e, sep,  true,  true, false); }
-    public    ElementNode question(final ElementNode e)                        { return new RepeatNode(e, null, true,  true, false); }
+    public    ElementNode question(final ElementNode e)                        { return new RepeatNode(e, null, true,  false, false); }
 
     //////////////////////////////////////////////////////////////////////////////
 
@@ -511,7 +516,7 @@ public class GrammarBuilder {
             } else {
                 ret = new Union(name, false);
                 map.put(name, ret);
-                nt.buildIntoPreallocatedUnion(this, nt, nt.drop(), ret);
+                nt.buildIntoPreallocatedUnion(this, nt, nt.drop(this), ret);
             }
             return ret;
         }
index 6308362..25581b2 100644 (file)
@@ -18,14 +18,21 @@ public class Repeat extends Union {
     protected Repeat(final Element e, boolean zeroOkay, boolean manyOkay, final Element separator, boolean maximal, Object tag) {
         this(e, zeroOkay, manyOkay, separator, maximal, tag, null); }
     protected Repeat(final Element e, boolean zeroOkay, boolean manyOkay, final Element separator, boolean maximal, Object tag, Atom follow) {
-        super(e+(!manyOkay ? "?" : (zeroOkay ? (maximal ? "**" : "*") : (maximal ? "++" : "+")))+(separator==null?"":("/"+separator)), true);
+        super(e
+              +(!manyOkay
+                ? "?"
+                : (zeroOkay
+                   ? (maximal ? "**" : "*")
+                   : (maximal ? "++" : "+")))
+              +(separator==null
+                ? ""
+                : ("/"+separator)),
+              true);
         if (zeroOkay && !manyOkay) {
             // FIXME
-            add(Sequence.create(new Element[0], tag).followedBy(follow));
-            add(Sequence.create(e).followedBy(follow));
-            return;
-        }
-        if (zeroOkay) {
+            add(Sequence.create(tag, new Element[] { }, null, false).followedBy(follow));
+            add(Sequence.create(tag, new Element[] { e }, null, false).followedBy(follow));
+        } else if (zeroOkay) {
             add(Sequence.create(tag, new Element[] { }, null, false).followedBy(follow));
             //add(new Sequence.Constant.Empty());
             // FUGLY
index 92ffe11..1197903 100644 (file)
@@ -323,7 +323,7 @@ testcase "a+2" {
 
 testcase "unnamed" {
     input "aaaaa";
-    output "top:{a q:{a a a} a}";
+    output "top:{a q a}";
 
     s = top:: z (q::"a"*) z
     z = a:: "a"
@@ -385,3 +385,13 @@ testcase "unnamed" {
   As = () | As "a"
   AAs = () | AAs "aa"
 }
+
+testcase "question mark" {
+  input "aa aba abba";
+  output "s:{Y Y Z}";
+  s = s:: X " " X " " X
+  X = Y > Z
+  Y = Y:: "a" B? "a"
+  Z = Z:: "a" "b"* "a"
+  B = "b"
+}