add LabelNode
[sbp.git] / src / edu / berkeley / sbp / meta / GrammarAST.java
index ed8fe94..586d519 100644 (file)
@@ -96,6 +96,7 @@ public class GrammarAST {
         if (head.equals("Elements")) return new Seq((ElementNode[])Reflection.rebuild(walkChildren(t), ElementNode[].class));
         if (head.equals("NonTerminalReference")) return new ReferenceNode(stringifyChildren(t.child(0)));
         if (head.equals(")"))   return new ReferenceNode(stringifyChildren(t.child(0)), true);
+        if (head.equals(":"))   return new LabelNode(stringifyChildren(t.child(0)), walkElement(t.child(1)));
         if (head.equals("::"))  return walkSeq(t.child(1)).tag(walkString(t.child(0)));
         if (head.equals("...")) return new DropNode(new RepeatNode(new TildeNode(new AtomNode()), null, true,  true,  false));
 
@@ -221,10 +222,18 @@ public class GrammarAST {
         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;
-        public String  sep = null;
+
+        /** 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) {
@@ -284,6 +293,7 @@ public class GrammarAST {
         }
     }
 
+    /** a NonTerminal is always a union at the top level */
     private class NonTerminalNode extends UnionNode {
         public boolean alwaysDrop;
         public String  name = null;
@@ -296,7 +306,18 @@ public class GrammarAST {
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) { return cx.get(name); }
     }
 
+    /** a sequence */
     private class Seq {
+        /** elements of the sequence */
+        ElementNode[] elements;
+        /** follow-set, if explicit */
+        ElementNode follow;
+        /** tag to add when building the AST */
+        String tag = null;
+        /** positive conjuncts */
+        HashSet<Seq> and = new HashSet<Seq>();
+        /** negative conjuncts */
+        HashSet<Seq> not = new HashSet<Seq>();
         public boolean alwaysDrop = false;
         public boolean isDropped(Context cx) {
             if (alwaysDrop) return true;
@@ -306,11 +327,6 @@ public class GrammarAST {
                     return false;
             return true;
         }
-        HashSet<Seq> and = new HashSet<Seq>();
-        HashSet<Seq> not = new HashSet<Seq>();
-        ElementNode[] elements;
-        ElementNode follow;
-        String tag = null;
         public Seq(ElementNode e) { this(new ElementNode[] { e }); }
         public Seq(ElementNode[] elements) { this(elements, true); }
         public Seq(ElementNode[] el, boolean check) {
@@ -413,6 +429,7 @@ public class GrammarAST {
         }
     }
 
+    /** reference to a NonTerminal by name */
     private class ReferenceNode extends ElementNode {
         public String nonTerminal;
         public boolean parenthesized;
@@ -440,6 +457,7 @@ public class GrammarAST {
         }
     }
 
+    /** a literal string */
     private class LiteralNode extends ElementNode {
         private String string;
         private final String thePrefix = prefix;
@@ -461,6 +479,7 @@ public class GrammarAST {
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) { return CharAtom.string(string); }
     }
 
+    /** an atom (usually a character class) */
     private class AtomNode extends ElementNode {
         char[][] ranges;
         public AtomNode() { this(new char[0][]); }
@@ -474,6 +493,7 @@ public class GrammarAST {
         }
     }
 
+    /** a repetition */
     private class RepeatNode extends ElementNode {
         public ElementNode e, sep;
         public final boolean zero, many, max;
@@ -500,6 +520,7 @@ public class GrammarAST {
         }
     }
 
+    /** helper class for syntactic constructs that wrap another construct */
     private abstract class ElementNodeWrapper extends ElementNode {
         protected ElementNode _e;
         public ElementNodeWrapper(ElementNode e) { this._e = e; }
@@ -508,11 +529,13 @@ public class GrammarAST {
         public Element build(Context cx, NonTerminalNode cnt, boolean dropall) { return _e.build(cx, cnt, dropall); }
     }
 
+    /** a backtick node indicating that, when building the AST, the node's children should be inserted here */
     private class BacktickNode extends ElementNodeWrapper {
         public BacktickNode(ElementNode e) { super(e); }
         public boolean isLifted() { return true; }
     }
 
+    /** negation */
     private class TildeNode extends ElementNodeWrapper {
         public TildeNode(ElementNode e) { super(e); }
         public Atom toAtom(Context cx) { return (Atom)((Topology<Character>)_e.toAtom(cx).complement()); }
@@ -524,6 +547,12 @@ public class GrammarAST {
         public boolean isDropped(Context cx) { return true; }
     }
 
+    /** provides a label on the fields of a Seq */
+    private class LabelNode extends ElementNodeWrapper {
+        public final String label;
+        public LabelNode(String label, ElementNode e) { super(e); this.label = label; }
+    }
+
     //////////////////////////////////////////////////////////////////////////////
 
     public class Context {