From b366a301b090a285c372f4fd77ab7472440f7d30 Mon Sep 17 00:00:00 2001 From: adam Date: Sun, 5 Mar 2006 02:01:05 -0500 Subject: [PATCH] added more flexible handling of Repeats -- now you can specify what they get tagged with (null by default) darcs-hash:20060305070105-5007d-94da880f63c6bfa30c0ceb607fbfde092515e1d4.gz --- src/edu/berkeley/sbp/Repeat.java | 28 ++++++++----- src/edu/berkeley/sbp/Sequence.java | 9 ++-- src/edu/berkeley/sbp/misc/MetaGrammar.java | 20 +++++---- src/edu/berkeley/sbp/misc/ReflectiveGrammar.java | 48 ++++++++++++++++++---- 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/edu/berkeley/sbp/Repeat.java b/src/edu/berkeley/sbp/Repeat.java index 4267b36..c68120e 100644 --- a/src/edu/berkeley/sbp/Repeat.java +++ b/src/edu/berkeley/sbp/Repeat.java @@ -11,26 +11,34 @@ import java.lang.ref.*; public class Repeat extends Union { /** repeat zero or one times */ - public static Repeat maybe(Element e) { return new Repeat(e, true, false); } + public static Repeat maybe(Element e) { return new Repeat(e, true, false, null, false); } + public static Repeat maybe(Element e, Object tag) { return new Repeat(e, true, false, null, false, tag); } /** repeat zero or more times */ - public static Repeat many0(Element e) { return new Repeat(e, true, true); } + public static Repeat many0(Element e) { return new Repeat(e, true, true, null, false); } + public static Repeat many0(Element e, Object tag) { return new Repeat(e, true, true, null, false, tag); } /** repeat zero or more times, separated by sep */ - public static Repeat many0(Element e, Element sep) { return new Repeat(e, true, true, sep); } + public static Repeat many0(Element e, Element sep) { return new Repeat(e, true, true, sep, false); } + public static Repeat many0(Element e, Element sep, Object tag) { return new Repeat(e, true, true, sep, false, tag); } /** repeat one or more times */ - public static Repeat many1(Element e) { return new Repeat(e, false, true); } + public static Repeat many1(Element e) { return new Repeat(e, false, true, null, false); } + public static Repeat many1(Element e, Object tag) { return new Repeat(e, false, true, null, false, tag); } /** repeat one or more times, separated by sep */ - public static Repeat many1(Element e, Element sep) { return new Repeat(e, false, true, sep); } + public static Repeat many1(Element e, Element sep) { return new Repeat(e, false, true, sep, false); } + public static Repeat many1(Element e, Element sep, Object tag) { return new Repeat(e, false, true, sep, false, tag); } /** repeat zero or more times, matching a maximal sequence of atoms */ public static Repeat maximal0(Element e) { return new Repeat(e, true, true, null, true); } + public static Repeat maximal0(Element e, Object tag) { return new Repeat(e, true, true, null, true, tag); } /** repeat one or more times, matching a maximal sequence of atoms */ public static Repeat maximal1(Element e) { return new Repeat(e, false, true, null, true); } + public static Repeat maximal1(Element e, Object tag) { return new Repeat(e, false, true, null, true, tag); } /** repeat one or more times, separated by an atom sep, matching a maximal sequence */ public static Repeat maximal1(Element e, Element sep) { return new Repeat(e, false, true, sep, true); } + public static Repeat maximal1(Element e, Element sep, Object tag) { return new Repeat(e, false, true, sep, true, tag); } - private Repeat(final Element e, boolean zeroOkay, boolean manyOkay) { this(e, zeroOkay, manyOkay, null); } - private Repeat(final Element e, boolean zeroOkay, boolean manyOkay, Element separator) { this(e, zeroOkay, manyOkay, separator, false); } private Repeat(final Element e, boolean zeroOkay, boolean manyOkay, final Element separator, boolean maximal) { + this(e, zeroOkay, manyOkay, separator, maximal, null); } + private Repeat(final Element e, boolean zeroOkay, boolean manyOkay, final Element separator, boolean maximal, Object tag) { super(e+(!manyOkay ? "?" : (zeroOkay ? (maximal ? "**" : "*") : (maximal ? "++" : "+")))+(separator==null?"":("/"+separator)), true); if (maximal && zeroOkay && separator != null) throw new RuntimeException("cannot create a maximal repetition of zero or more items with a separator (yet): " + this); @@ -39,11 +47,11 @@ public class Repeat extends Union { if (manyOkay) add(new Sequence.Singleton(many1(e, separator))); else add(new Sequence.Singleton(e)); } else { - add(new Sequence.RewritingSequence(null, new Element[] { e }, null)); + add(new Sequence.RewritingSequence(tag, new Element[] { e }, null)); if (separator==null) - add(new Sequence.Unwrap(new Element[] { e, Repeat.this })); + add(new Sequence.Unwrap(new Element[] { e, Repeat.this }, tag)); else - add(new Sequence.Unwrap(new Element[] { e, separator, Repeat.this }, new boolean[] { false, true, false })); + add(new Sequence.Unwrap(new Element[] { e, separator, Repeat.this }, tag, new boolean[] { false, true, false })); } if (maximal) for(Sequence s : this) s.noFollow = separator==null ? e : separator; } diff --git a/src/edu/berkeley/sbp/Sequence.java b/src/edu/berkeley/sbp/Sequence.java index 4d9e41f..7071ecb 100644 --- a/src/edu/berkeley/sbp/Sequence.java +++ b/src/edu/berkeley/sbp/Sequence.java @@ -197,18 +197,19 @@ public abstract class Sequence extends Element implements Iterable { public static class Unwrap extends Sequence { private boolean[] drops; - public Unwrap(Element[] e) { super(e); this.drops = null; } - public Unwrap(Element[] e, boolean[] drops) { super(e); this.drops = drops; } + private final Object tag; + public Unwrap(Element[] e, Object tag) { super(e); this.drops = null; this.tag = tag; } + public Unwrap(Element[] e, Object tag, boolean[] drops) { super(e); this.drops = drops; this.tag = tag; } Sequence _clone() { return new Unwrap(elements, drops); } public Forest postReduce(Input.Location loc, Forest[] args, Position p) { for(int i=0; i[] args2 = new Forest[count]; int j = 0; for(int i=0; i t : tree.children()) walk(t); return this; } - else if ("*".equals(head)) return Repeat.many0((Element)walk(tree.child(0))); - else if ("+".equals(head)) return Repeat.many1((Element)walk(tree.child(0))); - else if ("+/".equals(head)) return Repeat.many1((Element)walk(tree.child(0)), (Element)walk(tree.child(1))); - else if ("*/".equals(head)) return Repeat.many0((Element)walk(tree.child(0)), (Element)walk(tree.child(1))); - else if ("++/".equals(head)) return Repeat.maximal1((Element)walk(tree.child(0)), (Element)walk(tree.child(1))); - else if ("**".equals(head)) return Repeat.maximal0((Element)walk(tree.child(0))); - else if ("++".equals(head)) return Repeat.maximal1((Element)walk(tree.child(0))); - else if ("?".equals(head)) return Repeat.maybe((Element)walk(tree.child(0))); + else if ("*".equals(head)) return Repeat.many0((Element)walk(tree.child(0)), repeatTag()); + else if ("+".equals(head)) return Repeat.many1((Element)walk(tree.child(0)), repeatTag()); + else if ("+/".equals(head)) return Repeat.many1((Element)walk(tree.child(0)), (Element)walk(tree.child(1)), repeatTag()); + else if ("*/".equals(head)) return Repeat.many0((Element)walk(tree.child(0)), (Element)walk(tree.child(1)), repeatTag()); + else if ("++/".equals(head)) return Repeat.maximal1((Element)walk(tree.child(0)), (Element)walk(tree.child(1)), repeatTag()); + else if ("**".equals(head)) return Repeat.maximal0((Element)walk(tree.child(0)), repeatTag()); + else if ("++".equals(head)) return Repeat.maximal1((Element)walk(tree.child(0)), repeatTag()); + else if ("?".equals(head)) return Repeat.maybe((Element)walk(tree.child(0)), repeatTag()); else if ("!".equals(head)) { Element e = (Element)walk(tree.child(0)); dropAll.add(e); return e; } else if ("&".equals(head)) return ((Sequence)walk(tree,0)).and(sequence(walk(tree, 1), true)); else if ("and".equals(head)) return ((Sequence)walk(tree,0)).and(sequence(walk(tree, 1), true)); @@ -186,6 +186,7 @@ public class MetaGrammar extends StringWalker { } public Object convertLabel(String label) { return label; } + public Object repeatTag() { return null; } public Object walk(String tag, Object[] argo) { if (argo.length==0) return super.walk(tag, argo); @@ -276,6 +277,7 @@ public class MetaGrammar extends StringWalker { for(int i=0; i t) throws Exception { return buildHead(t, null); } public Object buildHead(Tree t, Class c) throws Exception { - System.out.println("buildHead " + (c==null?null:c.getName()) + " " + t); + //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 (h != null && h instanceof ClassMark) { + String clazz = ReflectiveWalker.mangle(((ClassMark)h).clazz); + Class c2 = (c!=null && c.getName().endsWith("$"+clazz)) ? c : Reflection.forNameOrNull(baseClass.getName()+"$"+clazz); + if (c2!=null) return buildBody(t, c2); + for(Method m : baseClass.getMethods()) { + if (!m.getName().equals(clazz)) continue; + Object[] o = new Object[m.getParameterTypes().length]; + for(int i=0; i=t.numChildren() ? null : buildHead(t.child(i), m.getParameterTypes()[i]); + return m.invoke(null, o); + } + throw new RuntimeException("couldn't figure out what to invoke for ClassMark " + clazz); + } else if (h==arrayMark && c==null) { + c = Object[].class; + } + if (c==null) System.out.println(h + " -- " + t.toPrettyString()); if (c.isArray()) { Object[] ret = new Object[t.numChildren()]; for(int i=0; i 0) throw new RuntimeException("can't buildHead() on a tree with children when the head is of type " + h.getClass().getName()); + if (t.numChildren() > 0) + throw new RuntimeException("can't buildHead() on a tree with children when the head is of type " + + h.getClass().getName() + "(c=="+(c==null?"null":c.getName())+")"); return h; } public Object buildBody(Tree t, Class c) throws Exception { System.out.println("buildBody " + (c==null?null:c.getName()) + " " + t); c = resolveClass(t, c); + if (c==null) return buildHead(t, null); Object o = c.newInstance(); Field[] f = c.getFields(); OUTER: for(int i=0; i t, Class c) throws Exception { if (c==null) return null; + if (c==int.class) return c; + if (c==String.class) return c; System.out.println("resolving " + c.getName()); if (Reflection.isConcrete(c)) return c; Class ret = null; @@ -99,6 +128,7 @@ public class ReflectiveGrammar extends MetaGrammar { throw new RuntimeException("couldn't decide between two classes:\n " + subs[i].getName() + "\n " + ret.getName()); ret = subs[i]; } + if (t.head()==null) return null; if (ret==null) throw new RuntimeException("couldn't find a class to match tree: " + t); return ret; } -- 1.7.10.4