checkpoint
authoradam <adam@megacz.com>
Sun, 12 Feb 2006 08:01:55 +0000 (03:01 -0500)
committeradam <adam@megacz.com>
Sun, 12 Feb 2006 08:01:55 +0000 (03:01 -0500)
darcs-hash:20060212080155-5007d-02db7f642cd71d9c42d75f72b557953269bc3b3b.gz

17 files changed:
Makefile
TODO
src/edu/berkeley/sbp/Forest.java
src/edu/berkeley/sbp/Sequence.java
src/edu/berkeley/sbp/misc/MetaGrammar.java
src/edu/berkeley/sbp/misc/ReflectiveGrammar.java [new file with mode: 0644]
src/edu/berkeley/sbp/misc/ReflectiveWalker.java
src/edu/berkeley/sbp/misc/RegressionTests.java
src/edu/berkeley/sbp/tib/Tib.java
src/edu/berkeley/sbp/tib/TibDoc.java
src/edu/berkeley/sbp/util/GraphViz.java
src/edu/berkeley/sbp/util/Reflection.java
tests/input.tibdoc
tests/meta.g
tests/regression.tc
tests/testcase.g
tests/tibdoc.g

index 3feab21..0cf5053 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,12 @@ test: edu.berkeley.sbp.jar
                tests/testcase.g \
                tests/regression.tc
 
+javatest: edu.berkeley.sbp.jar
+       $(java) -cp $< edu.berkeley.sbp.misc.RegressionTests \
+               tests/meta.g \
+               tests/testcase.g \
+               tests/java.tc
+
 boot: edu.berkeley.sbp.jar
        cd src; \
        $(java) -cp ../$< \
diff --git a/TODO b/TODO
index f059a77..d7afed2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,25 @@
 _____________________________________________________________________________
 Immediately
 
+- If a top-level rule has labels but no head-tag, like this
+    Foo = a:Bar b:Baz
+  then infer the name of the rule it belongs to
+
+create( $c:{...}, class ) =
+  return create($c:{...})
+
+create( h:{...}, class ) = 
+
+create( , String)
+
+create( _:{...}, String) = treat as char[]
+create( _:{...}, c[] )   = { create(.,c), create(.,c), ... }
+
+create( $c:{...} ) =
+
+
+  - clean up the visualization (?)
+
   - I still don't like Atom.Infer and Atom.Invert...
 
   - better ambiguity debugging tools
index d47e721..bfa4ecc 100644 (file)
@@ -39,7 +39,9 @@ public abstract class Forest<T> /*extends PrintableTree<Forest.MyBody<T>>*/ impl
         public void addTree(Tree<T> t);
     }
     public static class HashSetTreeConsumer<T> extends HashSet<Tree<T>> implements TreeConsumer<T> {
-        public void addTree(Tree<T> t) { super.add(t); }
+        public void addTree(Tree<T> t) {
+            super.add(t);
+        }
     }
 
     static        <T> Forest<T> singleton(Input.Location loc, Position p) {
@@ -58,6 +60,7 @@ public abstract class Forest<T> /*extends PrintableTree<Forest.MyBody<T>>*/ impl
         void expand(int i, TreeMaker<T> h);
     }
     public abstract void edges(GraphViz.Node n);
+    public boolean ambiguous() { return false; }
     protected static class MyBody<T> extends Forest<T> implements Body<T> /* extends PrintableTree<Forest<T>> implements */ {
 
         public boolean isTransparent() { return false; }
@@ -67,6 +70,7 @@ public abstract class Forest<T> /*extends PrintableTree<Forest.MyBody<T>>*/ impl
             GraphViz.Node n = gv.createNode(this);
             n.label = headToString()==null?"":headToString();
             n.directed = true;
+            n.comment = reduction==null?null:reduction+"";
             edges(n);
             return n;
         }
@@ -75,7 +79,7 @@ public abstract class Forest<T> /*extends PrintableTree<Forest.MyBody<T>>*/ impl
             if (edges) return;
             edges = true;
             for(int i=0; i<tokens.length; i++) {
-                if (i==tokens.length-1 && unwrap) {
+                if (i==tokens.length-1 && unwrap && !tokens[i].ambiguous()) {
                     tokens[i].edges(n);
                 } else {
                     n.edge(tokens[i], labels==null?null:labels[i]);
@@ -152,6 +156,11 @@ public abstract class Forest<T> /*extends PrintableTree<Forest.MyBody<T>>*/ impl
      *  viewed, it becomes immutable
      */
     static class Ref<T> extends Forest<T> {
+        public boolean ambiguous() {
+            if (hp.size()==0) return false;
+            if (hp.size()==1) return hp.iterator().next().ambiguous();
+            return true;
+        }
         private FastSet<Forest<T>> hp = new FastSet<Forest<T>>();
         public Ref() { }
         public int toInt() {
@@ -162,9 +171,12 @@ public abstract class Forest<T> /*extends PrintableTree<Forest.MyBody<T>>*/ impl
 
         public boolean isTransparent() { return hp.size()==1; }
         public boolean isHidden() { return hp.size()==0; }
-        public void edges(GraphViz.Node n) { for(Forest f : hp) f.edges(n); }
+        public void edges(GraphViz.Node n) {
+            if (hp.size()==1) { hp.iterator().next().edges(n); return; }
+            for(Forest f : hp) f.edges(n);
+        }
         public GraphViz.Node toGraphViz(GraphViz gv) {
-            if (hp.size()==0) return null;
+            //if (hp.size()==0) return null;
             if (hp.size()==1) return hp.iterator().next().toGraphViz(gv);
             if (gv.hasNode(this)) return gv.createNode(this);
             GraphViz.Node n = gv.createNode(this);
index fb1262f..4d9e41f 100644 (file)
@@ -228,10 +228,11 @@ public abstract class Sequence extends Element implements Iterable<Element> {
         }
         public <T> Forest<T> postReduce(Input.Location loc, Forest<T>[] args, Position p) {
             Forest<T>[] args2 = new Forest[count];
+            Object[] labs2 = new Object[count];
             int j = 0;
-            for(int i=0; i<args.length; i++) if (!drops[i]) args2[j++] = args[i];
+            for(int i=0; i<args.length; i++) if (!drops[i]) { labs2[j] = labs==null?null:labs[i]; args2[j++] = args[i]; }
             //System.out.println("reduce \""+tag+"\"");
-            return Forest.create(loc, (T)tag, args2, labs, false, false, p);
+            return Forest.create(loc, (T)tag, args2, labs2, false, false, p);
         }
         public StringBuffer toString(StringBuffer sb, boolean spacing) {
             int len = sb.length();
index a83d3ed..33b3b11 100644 (file)
@@ -136,8 +136,10 @@ public class MetaGrammar extends StringWalker {
             carets.put(ret, s);
             dropAll.add(ret);
             return ret;
+            /*
         } else if ("^^".equals(head)) {
             return new Keep(walk(tree,0));
+            */
         } else if ("psx".equals(head)) return ((PreSequence)walk(tree, 0)).buildSequence();
         else if ("nonTerminal".equals(head)) return getNonTerminal(string(tree.child(0)));
         else if ("::=".equals(head)) return nonTerminal(string(tree.child(0)), (Sequence[][])Reflection.lub(walk(tree, 1)), false, false);
@@ -155,10 +157,12 @@ public class MetaGrammar extends StringWalker {
         else if ("ps".equals(head)) return new PreSequence((Object[])walk(tree,0), null);
         else if (":".equals(head)) {
             String s = string(tree.child(0));
-            return new Keep("_".equals(s)?walk(tree,1):new PreSequence(new Object[] { walk(tree, 1) }, convertLabel(s)).buildUnion());
+            return new Keep(s,walk(tree,1));
         } else if ("::".equals(head)) {
             PreSequence p = (PreSequence)walk(tree, 1);
-            p.tag = convertLabel(string(tree.child(0)));
+            String s = string(tree.child(0));
+            if (s.equals("[]")) p.unwrap = true;
+            else p.tag = convertLabel(s);
             return p;
         }
         else if ("=>".equals(head)) {
@@ -176,11 +180,12 @@ public class MetaGrammar extends StringWalker {
     }
 
     static class Keep {
-        final Object o;
-        public Keep(Object o) { this.o = o; }
+        public final String label;
+        public final Object o;
+        public Keep(String label, Object o) { this.label = label; this.o = o; }
     }
 
-    public String convertLabel(String label) { return label; }
+    public Object convertLabel(String label) { return label; }
 
     public Object walk(String tag, Object[] argo) {
         if (argo.length==0) return super.walk(tag, argo);
@@ -199,7 +204,7 @@ public class MetaGrammar extends StringWalker {
         public Element noFollow = null;
         public final HashSet<Sequence> and  = new HashSet<Sequence>();
         public final HashSet<Sequence> not  = new HashSet<Sequence>();
-        public /*final*/ String tag;
+        public /*final*/ Object tag;
         public final Object[] o;
 
         public PreSequence sparse(Object e) {
@@ -234,8 +239,8 @@ public class MetaGrammar extends StringWalker {
         boolean[] drops = null;
         public PreSequence(Object o) { this(new Object[] { o }, null); }
         public PreSequence(Object[] o) { this(o, null); }
-        public PreSequence(Object[] o, String tag) { this(o, tag, null); }
-        public PreSequence(Object[] o, String tag, boolean[] drops) {
+        public PreSequence(Object[] o, Object tag) { this(o, tag, null); }
+        public PreSequence(Object[] o, Object tag, boolean[] drops) {
             this.o = o;
             this.tag = tag;
             this.drops = drops==null ? new boolean[o.length] : drops;
@@ -250,7 +255,7 @@ public class MetaGrammar extends StringWalker {
         public boolean unwrap = false;
         public Sequence buildSequence() { return buildSequence(null, false, false); }
         public Sequence buildSequence(Union u) { return buildSequence(u, false, false); }
-        public Sequence buildSequence(Union u, boolean lame, String tag) {
+        public Sequence buildSequence(Union u, boolean lame, Object tag) {
             this.tag = tag;
             return buildSequence(u, lame, false);
         }
@@ -263,6 +268,7 @@ public class MetaGrammar extends StringWalker {
             }
             HashSet<Sequence> set = new HashSet<Sequence>();
             Element[] o2 = o==null ? new Element[0] : new Element[o.length];
+            Object[] labels = new Object[drops.length];
             int nonDrop = 0;
             boolean keeping = false;
             if (o != null) {
@@ -273,6 +279,7 @@ public class MetaGrammar extends StringWalker {
                         if (!keeping) { for(int k=0; k<i; k++) drops[k]=true; }
                         drops[i] = false;
                         keeping = true;
+                        labels[i] = ((Keep)oi).label;
                         oi = ((Keep)oi).o;
                     } else {
                         if (keeping) drops[i] = true;
@@ -292,7 +299,7 @@ public class MetaGrammar extends StringWalker {
             Sequence ret = null;
             if (dropAll || lame) ret = Sequence.drop(expansion, lame);
             else if (unwrap)    ret = new Sequence.Unwrap(expansion, drops);
-            else if (tag!=null) ret = Sequence.rewritingSequence(tag, expansion, null, drops);
+            else if (keeping || tag!=null) ret = Sequence.rewritingSequence(tag, expansion, labels, drops);
             else {
                 int idx = -1;
                 for(int i=0; i<expansion.length; i++)
@@ -492,6 +499,9 @@ public class MetaGrammar extends StringWalker {
 
 
 
+
+
+
         // DO NOT EDIT STUFF BELOW: IT IS AUTOMATICALLY GENERATED
 new edu.berkeley.sbp.Tree(null, "grammar", new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, null, new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "=", new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, null, new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "s", new edu.berkeley.sbp.Tree[] { })}),
         new edu.berkeley.sbp.Tree(null, null, new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, null, new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "psx", new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "ps", new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, null, new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "!", new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "nonTerminal", new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, null, new edu.berkeley.sbp.Tree[] { new edu.berkeley.sbp.Tree(null, "w", new edu.berkeley.sbp.Tree[] { }),
@@ -1143,3 +1153,6 @@ new edu.berkeley.sbp.Tree(null, "grammar", new edu.berkeley.sbp.Tree[] { new edu
 
 
 
+
+
+
diff --git a/src/edu/berkeley/sbp/misc/ReflectiveGrammar.java b/src/edu/berkeley/sbp/misc/ReflectiveGrammar.java
new file mode 100644 (file)
index 0000000..ecf186d
--- /dev/null
@@ -0,0 +1,106 @@
+package edu.berkeley.sbp.misc;
+import java.io.*;
+import java.util.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.tib.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.util.*;
+
+public class ReflectiveGrammar extends MetaGrammar {
+
+    final Class baseClass;
+    public ReflectiveGrammar(Class baseClass) { this.baseClass = baseClass; }
+
+    public Object convertLabel(String label) { return new ClassMark(label); }
+
+    private static class ClassMark {
+        public final String clazz;
+        public ClassMark(String clazz) { this.clazz = clazz; }
+        public String toString() { return clazz+"$"; }
+    }
+
+    public String stringify(Tree<Object> t) throws Exception {
+        StringBuffer ret = new StringBuffer();
+        for(int i=0; i<t.numChildren(); i++) {
+            Tree<Object> child = t.child(i);
+            Object head = child.numChildren() > 0 ? buildHead(child, String.class) : child.head();
+            if (head!=null) ret.append(head);
+        }
+        return ret.toString();
+    }
+
+    public Object build(Tree<Object> t) throws Exception { return buildHead(t, null); }
+    public Object buildHead(Tree<Object> t, Class c) throws Exception {
+        System.out.println("buildHead " + (c==null?null:c.getName()) + " " + t);
+        Object h = t.head();
+
+        if (h != null && h instanceof ClassMark) return buildBody(t, Class.forName(baseClass.getName()+"$"+((ClassMark)h).clazz));
+        if (c.isArray()) {
+            Object[] ret = new Object[t.numChildren()];
+            for(int i=0; i<ret.length; i++)
+                ret[i] = buildHead(t.child(i), c.getComponentType());
+            return Reflection.lub(ret);
+        }
+        if (h==null)                return buildBody(t, c);
+        
+        if (c==String.class) return stringify(t);
+        if (c==int.class)    return new Integer(stringify(t));
+
+        if (t.numChildren() > 0) throw new RuntimeException("can't buildHead() on a tree with children when the head is of type " + h.getClass().getName());
+        return h;
+    }
+
+    public Object buildBody(Tree<Object> t, Class c) throws Exception {
+        System.out.println("buildBody " + (c==null?null:c.getName()) + " " + t);
+        c = resolveClass(t, c);
+        Object o = c.newInstance();
+        Field[] f = c.getFields();
+        OUTER: for(int i=0; i<t.numChildren(); i++) {
+            Object label = t.label(i);
+            Field field = null;
+            if (label!=null) try { field = c.getField(label+""); } catch (NoSuchFieldException _) { }
+            if (field==null && label != null)
+                for(Method m : c.getMethods())
+                    if (m.getName().equals(label)) {
+                        m.invoke(o, new Object[] { buildHead(t.child(i), m.getParameterTypes()[0]) });
+                        continue OUTER;
+                    }
+            if (field==null) System.err.println("warning: skipping field " + label + " ("+i+") on class " + c.getName());
+            else {
+                Object tgt = Reflection.rebuild(buildHead(t.child(i), field.getType()), field.getType());
+                if (tgt instanceof Object[]) tgt = Reflection.lub(tgt);
+                System.err.println("setting field " + field.getName() + " on " + c.getName() + " to " + tgt);
+                try {
+                    field.set(o, tgt);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return o;
+    }
+
+    public Class resolveClass(Tree<Object> t, Class c) throws Exception {
+        if (c==null) return null;
+        System.out.println("resolving " + c.getName());
+        if (Reflection.isConcrete(c)) return c;
+        Class ret = null;
+        Class[] subs = (Class[])c.getField("subclasses").get(null);
+        OUTER: for(int i=0; i<subs.length; i++) {
+            System.err.println("trying " + subs[i].getName());
+            for(int j=0; j<t.numChildren(); j++)
+                if (Reflection.getField(subs[i], t.label(j)+"")==null) {
+                    System.err.println("skipping due to " + t.label(j));
+                    continue OUTER;
+                }
+            if (ret != null)
+                throw new RuntimeException("couldn't decide between two classes:\n  " + subs[i].getName() + "\n  " + ret.getName());
+            ret = subs[i];
+        }
+        if (ret==null) throw new RuntimeException("couldn't find a class to match tree: " + t);
+        return ret;
+    }
+
+}
index 186fa3b..ad057a7 100644 (file)
@@ -10,7 +10,7 @@ public class ReflectiveWalker extends StringWalker {
     public ReflectiveWalker()              { this.target = this; }
     public ReflectiveWalker(Object target) { this.target = target; }
     private final Object target;
-    private String normalize(String s) {
+    public static String mangle(String s) {
         StringBuffer ret = new StringBuffer();
         for(int i=0; i<s.length(); i++) {
             char c = s.charAt(i);
@@ -57,7 +57,7 @@ public class ReflectiveWalker extends StringWalker {
     /*
     public Object walk(Tree<String> tree) {
         if (tree.head()!=null) {
-            Member m = member("$"+normalize(tree.head()), 0, false);
+            Member m = member("$"+mangle(tree.head()), 0, false);
             if (m!=null) {
                 if ((m instanceof Method) && ((Method)m).getReturnType()==Void.TYPE) {
                     Reflection.fuzzyInvoke(target, m, new Object[0]);
@@ -69,7 +69,7 @@ public class ReflectiveWalker extends StringWalker {
     */
     public void walk(String tag) {
         if (tag==null) return;
-        Member m = member(normalize(tag), 0, false);
+        Member m = member(mangle(tag), 0, false);
         if (m!=null) Reflection.fuzzyInvoke(target, m);
     }
     protected Object defaultWalk(String tag, Object[] argo) { return super.walk(tag, argo); }
@@ -77,7 +77,7 @@ public class ReflectiveWalker extends StringWalker {
         if (argo.length==0) return super.walk(tag, argo);
         if (argo==null) return tag;
         if (tag==null || "".equals(tag)) return argo;
-        Member m = tag==null ? null : member(normalize(tag), argo.length, false);
+        Member m = tag==null ? null : member(mangle(tag), argo.length, false);
         if (m==null) return defaultWalk(tag, argo);
         //System.out.println("preparing to invoke method " + (m==null ? "null" : (m.toString())) + " for sequence " + (owner()+"."+tag));
         if (m != null) return Reflection.fuzzyInvoke(target, m, argo);
index b31d5c3..beb7110 100644 (file)
@@ -81,9 +81,14 @@ public class RegressionTests {
         }
         public boolean execute() throws Exception {
             if (jav) {
-                Tree<Object> tree = new CharParser(grammar).parse(new StringReader(input)).expand1();
-                System.out.println(tree);
-                System.out.println(JavaGrammar.build(tree));
+                Forest<String> tree = new CharParser(grammar).parse(new StringReader(input));
+                FileOutputStream fos = new FileOutputStream("/Users/megacz/Desktop/out.dot");
+                PrintWriter p = new PrintWriter(new OutputStreamWriter(fos));
+                GraphViz gv = new GraphViz();
+                tree.toGraphViz(gv);
+                gv.dump(p);
+                p.flush();
+                p.close();
                 return true;
             }
             Forest<String> res = null;
@@ -143,7 +148,7 @@ public class RegressionTests {
                     String[] output = tree.numChildren()>2 ? ((String[])walk(tree, 1)) : new String[0];
                     boolean tib = "tibcase".equals(tree.head());
                     boolean jav = "javacase".equals(tree.head());
-                    MetaGrammar gram = jav ? new JavaGrammar() : tib ? new Tib.Grammar() : new MetaGrammar();
+                    MetaGrammar gram = jav ? new JavaGrammar() : tib ? /*new Tib.Grammar()*/null : new MetaGrammar();
                     Union grammar = (Union)((MetaGrammar)(gram.walk(tree, tree.numChildren()-1))).done("s");
                     return new TestCase(input, output, grammar, tib, jav);
                 } else if ("ts".equals(tree.head())) return walk(tree, 0);
index 0ce53b0..f802ab0 100644 (file)
@@ -135,10 +135,10 @@ public class Tib implements Input<Character> {
 
     // Grammar //////////////////////////////////////////////////////////////////////////////
 
-    public static class Grammar extends MetaGrammar {
+    public static class Grammar extends ReflectiveGrammar {
         private int anon = 0;
         private final Element ws = Repeat.maximal0(getNonTerminal("w"));
-        public Grammar() { dropAll.add(ws); }
+        public Grammar(Class c) { super(c); dropAll.add(ws); }
         public Object walk(Tree<String> tree) {
             String head = tree.head();
             if (tree.numChildren()==0) return super.walk(tree);
index f3195ec..705ac3e 100644 (file)
@@ -12,22 +12,49 @@ import java.io.*;
 
 public class TibDoc {
 
+    public static class Doc {
+        public Header head;
+        public Body   body;
+    }
+    public static class kv { public String key; public Text[] val; }
+    public static class Header {
+        public void attrs(kv[] kvs) {
+            for(int i=0; i<kvs.length; i++)
+                System.out.println("key="+kvs[i].key+" val="+kvs[i].val);
+        }
+    }
+    public static class Body {
+        Section[] sections;
+    }
+    public static class Section { }
+    public static abstract class Text {
+        public static final Class[] subclasses = new Class[] { Chars.class, URL.class, Email.class };
+    }
+    public static class Chars extends Text  { String chars; }
+    public static class Symbol extends Text { String chars; }
+    public static class Email extends Text  { String user;  Host host; }
+    public static interface Host { }
+    public static class DNS implements Host { String[] part; }
+    public static class IP  implements Host { int a, b, c, d; }
+    public static class URL extends Text    { String method; Host host; int port; String path; }
+    public static class Italic extends Text { Text body; }
+
     public static void main(String[] s) throws Exception {
         try {
             System.out.println("parsing " + s[0]);
             Tree<String> res = new CharParser(MetaGrammar.make()).parse(new FileInputStream(s[0])).expand1();
-            MetaGrammar gram = (MetaGrammar)new Tib.Grammar().walk(res);
+            MetaGrammar gram = new Tib.Grammar(TibDoc.class);
+            gram = (MetaGrammar)gram.walk(res);
             //System.out.println(gram);
             Union mg = gram.done();
             
             System.out.println("\nparsing " + s[1]);
             Forest f = new CharParser(mg).parse(new Tib(new FileInputStream(s[1])));
-            
+            //((Tree)new StringifyWalker().walk(f.expand1())).toPrettyString()
             System.out.println();
-            System.out.println(f);
-            System.out.println();
-            System.out.println(((Tree)new StringifyWalker().walk(f.expand1())).toPrettyString());
-            
+            Doc doc = (Doc)new ReflectiveGrammar(TibDoc.class).build(f.expand1());
+            System.out.println(doc);
+            /*
             String st = new HTMLWalker().walk(f.expand1()).toString();
             System.out.println(st);
             FileOutputStream fos = new FileOutputStream("out.html");
@@ -35,6 +62,7 @@ public class TibDoc {
             p.println(st);
             p.flush();
             p.close();
+            */
         } catch (Ambiguous a) {
             FileOutputStream fos = new FileOutputStream("/Users/megacz/Desktop/out.dot");
             PrintWriter p = new PrintWriter(new OutputStreamWriter(fos));
@@ -43,6 +71,7 @@ public class TibDoc {
             gv.dump(p);
             p.flush();
             p.close();
+            a.printStackTrace();
             
         } catch (Exception e) {
             e.printStackTrace();
@@ -79,6 +108,7 @@ public class TibDoc {
         public String ul(String[] li) { return "<ul>"+join(li,"")+"</ul>"; }
         public String ol(String[] li) { return "<ol>"+join(li,"")+"</ol>"; }
         public String hr() { return "\n<hr/>\n"; }
+        public String br() { return "\n<br/>\n"; }
         public String it(Object o) { return "<i>"+o+"</i>"; }
         public String tt(Object o) { return "<tt>"+o+"</tt>"; }
         public String underline(Object o) { return "<ul>"+o+"</ul>"; }
index bfef2f6..86d0d50 100644 (file)
@@ -20,6 +20,7 @@ public class GraphViz {
     public class Node {
         private final int idx = master_idx++;
         public String label;
+        public String comment;
         public boolean directed = false;
         public String color="black";
         public ArrayList<Node> edges = new ArrayList<Node>();
@@ -89,6 +90,7 @@ public class GraphViz {
                 pw.print("\"");
             }
             pw.print("color="+color);
+            if (comment!=null) pw.print(" comment=\""+StringUtil.escapify(comment,"\\\"")+"\" ");
             pw.print("];\n");
         }
     }
index 24ef420..5c13668 100644 (file)
@@ -146,4 +146,13 @@ public final class Reflection {
         return true;
     }
 
+    public static Field getField(Class c, String s) {
+        try {
+            for(Field f : c.getDeclaredFields())
+                if (f.getName().equals(s))
+                    return f;
+        } catch (Exception e) { }
+        return null;
+    }
+
 }
index d6b7415..37d779f 100644 (file)
@@ -1,16 +1,15 @@
 header
   author   = Adam Megacz
   myemail  = adam@foo.megacz.com
-  comment  = my homepage is at http://www.megacz.com you should *check* it out
-  date     = published \today, yep!
+  comment  = my homepage is at http://www.megacz.com you should **check** it out
 
 == Introduction ==
 
-  this is the body adam@megacz.com text
+  this is the body adam@megacz.com text \today
   You can visit {my website}->adam@megacz.com with a !hyperlink to it!
 
-  The following demonstrates verbatim stuff [[Knu68]], as
-  well as a footnote ((like)) because are
+  The following demonstrates->http://www.slashdot.org/ verbatim stuff [[Knu68]], as
+  well \br as \br a \br footnote ((like)) because are
   coool in an O(n^^3) way.
 
   "" this is a test of \sc{paragraph of fun}
index 72e1665..3ee8fdf 100644 (file)
@@ -28,8 +28,7 @@ Range         = range:: ec
               |         ec ^"-" ec
 
 e             =                (Quoted|Word) ^":" e
-              > 
-              nonTerminal::          Word
+              > nonTerminal::          Word
               | literal::       Quoted
               |                  ^"()"
               |                  ^"{" PreSequence "}"       /ws
index 78d35e3..af600f3 100644 (file)
@@ -357,4 +357,5 @@ testcase {
     input "aaaaa";
     s = top:: z (q::"a"*) z
     z = a:: "a"
-}
\ No newline at end of file
+}
+
index af69317..8bb684c 100644 (file)
@@ -5,5 +5,7 @@ test       =      ^"testcase" "{" input output +/ ws   (grammar::Grammar) "}" /w
            |      ^"testcase" "{" input                (grammar::Grammar) "}" /ws
            |      ^"tibcase"  "{" input output +/ ws   (grammar::Grammar) "}" /ws
            |      ^"tibcase"  "{" input                (grammar::Grammar) "}" /ws
+           |      ^"javacase"  "{" input output +/ ws   (grammar::Grammar) "}" /ws
+           |      ^"javacase"  "{" input                (grammar::Grammar) "}" /ws
 output     =      ^"output" Quoted ";" /ws
 input      =      "input"  Quoted ";" /ws
index 4a57992..7841855 100644 (file)
 //   [1] http://...
 //
 
-// consider ++bold++ and **italic**?
-// \br
 // nonbreaking text?
-// ellipsis detection (...)
 // degree: 15^o
 // Arrows: <- -> => <= <->
 
@@ -39,7 +36,6 @@
 // #include
 
 // simple macros (#define) (\define)
-// today's date
 
 // table representation
 //  
@@ -58,11 +54,11 @@ nw         = ~[\r\n\ ]
 
 //////////////////////////////////////////////////////////////////////////////
 
-s                   = top:: Doc
+s                   = Doc
 
-Doc                 = doc::    {Header} Body                   /ws
-Header              = header:: "header" { kv */ ws }           /ws
-Body                = body::   Section*/ws
+Doc                 = Doc:: head:{Header} body:Body   /ws
+Header              = Header:: "header" attrs:{ kv */ ws }     /ws
+Body                = sections:Section*/ws
 Section             = { section:: SectionHeader Paragraph* /ws }
 SectionHeader       = "==" SectionHeaderBody "=="
 SectionHeaderBody   =  "=" SectionHeaderBody "="
@@ -71,7 +67,7 @@ SectionHeaderBody   =  "=" SectionHeaderBody "="
 sp       = " "**
 blank    = !sp "\n" !sp "\n" !ws
 
-kv           = kv1:: word "=" text /ws
+kv           = kv:: key:word "=" val:text /ws
 wp           = w++
 num          = [0-9]++
 Paragraph    = blockquote:: { "\"\"" !ws  text }
@@ -81,25 +77,23 @@ Paragraph    = blockquote:: { "\"\"" !ws  text }
 onums        = nums !(". "|") ")
 any          = ~[]*
 
-uli          = li:: "* "          (!ws text &~ any (oli|uli))
+uli          = li:: "* "         (!ws text &~ any (oli|uli))
 oli          = li:: ("# "|onums) (!ws text &~ any (oli|uli))
 
-//
-
-text         = text:: Item
+text         = Item
 Itemx        = !ws Item
              | ()
 Item         = blockquote
              > "[]":: { ul:: uli+/ws }          Itemx
              | "[]":: { ol:: oli+/ws }          Itemx
              > "[]":: pre                       Itemx
+             > "[]":: link                      Itemx
              > "[]":: structured                Itemx
-             > "[]":: structuredx               Itemx
              > "[]":: styled                    Itemx
+             > "[]":: (Chars:: alphanum++)      Itemx
              > "[]":: qtext                     Itemx
-             > "[]":: (stringify:: alphanum++)  Itemx
              > "[]":: symbol                    Itemx
-             > "[]":: (stringify:: sym++)       Itemx
+             > "[]":: (Symbol:: sym++)          Itemx
              > "[]":: Paragraph                 Itemx
 
 blockquote   = blockquote:: "\"\"" text "\"\""
@@ -108,31 +102,32 @@ blockquote   = blockquote:: "\"\"" text "\"\""
 qtext        = quoted:: "\"" text "\""
 pre          = verbatim:: "[verbatim]" { ~[]+ } /ws   // FIXME doesn't work
 
-styled       = underline:: "__" text "__"      
-             | footnote:: "((" text "))"      
-             | ( tt:: "[[" text "]]"    
-             | citation::   "[" text "]"     
-               )
+styled       = underline::     "__" text "__"      
+             | footnote::      "((" text "))"      
+             | tt::            "[[" text "]]"
+             | citation::       "[" word "]"
              | strikethrough:: "!!" text "!!"      
-             | superscript:: "^^" (word|block)   
-             | subscript:: ",," (word|block)   
-             | smallcap:: "\\sc" block        
-             | bold:: "**" text "**"      
-             | keyword:: "!" (word|block)    
-             > it:: "*" text "*"
+             | superscript::   "^^" (word|block)   
+             | subscript::     ",," (word|block)   
+             | smallcap::      "\\sc" block        
+             | bold::           "++" text "++"
+             | keyword::         "!" (word|block)    
+             | Italic::         "**" text "**"
 
-//
+block         = { text }
+
+link          = link:: text:({ text })     "->" href:(url|email)
+              > link:: text:alphanum++ !ws "->" href:(url|email)
 
-block   = { text }
-structured   = link:: { text } "->" (url|email)
-              //> alphanum++ "->" (url|email) => link
-structuredx   = glyph
+structured    = command & "\\" [a-zA-Z0-9]++ block?
+              > glyph
               > email
               > url
 
-glyph        = "(r)" | "(c)" | "(tm)" | "--"  // euro symbol?
-             | today:: "\\today" -> ~[a-z]
+glyph        = euro:: "(e)" | "(r)" | "(c)" | "(tm)" | "--" | "..."
 
+command      = today:: "\\today"
+             | bre::   "\\br"
 
 // URLs //////////////////////////////////////////////////////////////////////////////
 
@@ -141,29 +136,31 @@ glyph        = "(r)" | "(c)" | "(tm)" | "--"  // euro symbol?
 // only gets parsed once
 
 urlpath      = urlchar*
-username     = stringify:: [a-zA-Z0-9;/?:&=$\-_.+]++
-password     = stringify:: [a-zA-Z0-9;/?:&=$\-_.+]++
-urlchar      = [a-zA-Z0-9;/?:&=$\-_.+@]
+username     = [a-zA-Z0-9;/?:&=$\-_.+]++
+password     = [a-zA-Z0-9;/?:&=$\-_.+]++
+urlc         = [a-zA-Z0-9;/?:&=$\-_.+@]
+urlv         = urlc | [%]
+urlchar      = urlc
              | "%":: "%" [0-9] [0-9]
-url          = "mailto" ":"   email
-             > url::   method "://" url_login? host (":" nums)? ("/" urlpath)?
+url          = "mailto" ":"   email -> ~urlv
+             > method:method "://" url_login? host:host port:(":" nums)? path:("/" urlpath)? -> ~urlv
 url_login    = login:: username (":" password) "@"
-method       = stringify:: [+\-.a-z0-9]+
-domain       = domain:: (part +/ ".") -> ~"."
-part         = stringify:: [a-zA-Z0-9\-]++
+method       = [+\-.a-z0-9]+
+domain       = (part +/ ".") -> ~"."
+part         = [a-zA-Z0-9\-]++
 // interesting use of boolean grammars
 //            &~ ([\-0-9] ~[]* | ~[]* [\-0-9])
 
-email        = emailaddr:: username "@" host -> ~[.]
-nums         = stringify:: [0-9]++
-host         = ip:: nums "." nums "." nums "." nums
-             | domain
+email        = user:username "@" host:host -> ~[.]
+nums         = [0-9]++
+host         = IP::  nums "." nums "." nums "." nums
+             | DNS:: domain
 
 
 
 // Tokens ///////////////////////////////////////////////////////////////////
 
-word       = stringify:: alphanum++
+word       = alphanum++
            | quoted
 
 quoted     = "\"" ((~[\"\\] | escaped)+) "\""