X-Git-Url: http://git.megacz.com/?p=sbp.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fsbp%2Fmeta%2FMetaGrammarBindings.java;h=196394a9de1a07ec89a30af67328cb228c82a06b;hp=9ccf8a8e8e515f588147a33511a827b9dc49de65;hb=24112db237318c030b4d4f457d90c34fd69d652b;hpb=11fb48ff93c4fad499e4110e4aa8883357963f6e diff --git a/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java b/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java index 9ccf8a8..196394a 100644 --- a/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java +++ b/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java @@ -10,13 +10,15 @@ import java.lang.reflect.*; import java.io.*; /** The java classes typically used to represent a parsed grammar AST; each inner class is a type of AST node. */ -public class MetaGrammarBindings { +public class MetaGrammarBindings extends AnnotationGrammarBindings { + + public MetaGrammarBindings() { super(MetaGrammarBindings.class); } // FIXME ugly ugly ugly scary dangerous public static String prefix = ""; - + /** A grammar (a set of nonterminals) */ - public static class GrammarNode extends HashMap implements NonTerminalSource { + public static class GrammarNode extends HashMap { public NonTerminalNode[] getNonTerminals() { return (NonTerminalNode[])values().toArray(new NonTerminalNode[0]); } @@ -28,9 +30,7 @@ public class MetaGrammarBindings { this.put(nt.name, nt); } } - public @bind.as("Grammar") GrammarNode(Object[] nt) { - add(nt); - } + public @bind.as("Grammar") GrammarNode(Object[] nt) { add(nt); } private void add(Object[] obs) { for(Object o : obs) { if (o==null) continue; @@ -41,7 +41,7 @@ public class MetaGrammarBindings { throw new RuntimeException("duplicate definition of nonterminal \""+nt.name+"\""); this.put(nt.name, nt); } - else if (o instanceof NonTerminalSource) add(((NonTerminalSource)o).getNonTerminals()); + else if (o instanceof GrammarNode) add(((GrammarNode)o).getNonTerminals()); } } public String toString() { @@ -49,7 +49,7 @@ public class MetaGrammarBindings { for(NonTerminalNode nt : values()) ret += nt + ", "; return ret + " ]"; } - public Union build(String s, GrammarBindingResolver rm) { + public Union build(String s, Grammar.Bindings rm) { Context cx = new Context(this,rm); Union u = null; for(MetaGrammarBindings.NonTerminalNode nt : values()) { @@ -64,11 +64,18 @@ public class MetaGrammarBindings { public abstract static class UnionNode extends ElementNode { public Seq[][] sequences; + public Atom toAtom(Context cx) { + Atom ret = null; + for(Seq[] ss : sequences) + for(Seq s : ss) + ret = ret==null ? s.toAtom(cx) : infer(ret.union(s.toAtom(cx))); + return ret; + } public void build(Context cx, Union u, NonTerminalNode cnt) { HashSet bad2 = new HashSet(); for(int i=0; i red = (Tree.TreeFunctor)t.head(); - return (MetaGrammarBindings.GrammarNode)red.invoke(t); + Tree t = new CharParser(MetaGrammar.newInstance()).parse(new FileInputStream("tests/"+fileName)).expand1(); + TreeFunctor red = (TreeFunctor)t.head(); + String oldprefix = prefix; + prefix = as; + GrammarNode gn = (GrammarNode)red.invoke(t); + prefix = oldprefix; + return gn; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } - public static interface NonTerminalSource { - public NonTerminalNode[] getNonTerminals(); - } - - public static class NonTerminalNode extends UnionNode implements NonTerminalSource { + public static class NonTerminalNode extends UnionNode { public boolean rep; public String name = null; public String sep = null; public NonTerminalNode[] getNonTerminals() { return new NonTerminalNode[] { this }; } - public @bind.as("NonTerminal") NonTerminalNode(@bind.arg String name, @bind.arg Seq[][] sequences) { this(name, sequences, false); } + public @bind.as("NonTerminal") NonTerminalNode(@bind.arg String name, @bind.arg Seq[][] sequences) { + this(name, sequences, false); } public NonTerminalNode(String name, Seq[][] sequences, boolean rep) { this(name, sequences, rep, null); } public NonTerminalNode(String name, Seq[][] sequences, boolean rep, String sep) { this.name = prefix + name; this.sequences = sequences; this.rep = rep; - this.sep = prefix + sep; + this.sep = sep==null?null:(prefix + sep); } public Element build(Context cx, NonTerminalNode cnt) { return cx.get(name); } public void build(Context cx, Union u, NonTerminalNode cnt) { if (!rep) { super.build(cx, u, this); return; } HashSet bad2 = new HashSet(); - Union urep = new Union(); + Union urep = new Union(null, false); urep.add(Sequence.empty); - urep.add(Sequence.singleton(new Element[] { cx.get(sep), u }, 1)); + if (sep != null) + urep.add(Sequence.singleton(new Element[] { cx.get(sep), u }, 1)); + else + urep.add(Sequence.singleton(new Element[] { u }, 0)); for(int i=0; i and = new HashSet(); HashSet not = new HashSet(); @@ -209,14 +199,21 @@ public class MetaGrammarBindings { } public Seq(ElementNode e) { this(new ElementNode[] { e }); } public Seq(ElementNode[] elements) { this.elements = elements; } - public Seq tag(String tag) { this.tag = tag; return this; } - public Seq follow(ElementNode follow) { this.follow = follow; return this; } + public Atom toAtom(Context cx) { + if (elements.length != 1) throw new Error("FIXME"); + return elements[0].toAtom(cx); + } + public Seq tag(String tag) { this.tag = prefix+tag; return this; } + public Seq follow(ElementNode follow) { + this.follow = follow; + return this; + } public Seq dup() { Seq ret = new Seq(elements); ret.and.addAll(and); ret.not.addAll(not); ret.follow = follow; - ret.tag = tag; + ret.tag = prefix+tag; return ret; } public Seq and(Seq s) { and.add(s); s.lame = true; return this; } @@ -241,7 +238,7 @@ public class MetaGrammarBindings { } public Sequence build0(Context cx, boolean lame, NonTerminalNode cnt) { boolean dropAll = lame; - if (tag!=null && "()".equals(tag)) dropAll = true; + if (tag!=null && tag.endsWith("()")) dropAll = true; boolean[] drops = new boolean[elements.length]; Element[] els = new Element[elements.length]; for(int i=0; i") Seq arrow(Seq s, ElementNode e) { return s.follow(e); } - public static @bind.as("::") Seq tag(String tagname, Seq s) { return s.tag(tagname); } - public static @bind.as("/") Seq slash(Seq s, ElementNode e) { return s.separate(e); } + public static @bind.as("&") Seq and2(Seq s, Seq a) { return s.and(a); } + public static @bind.as("&~") Seq andnot2(Seq s, Seq a) { return s.andnot(a); } + public static @bind.as("->") Seq arrow(Seq s, ElementNode e) { return s.follow(e); } + public static @bind.as("::") Seq tag(String tagname, Seq s) { return s.tag(tagname); } + public static @bind.as("/") Seq slash(Seq s, ElementNode e) { return s.separate(e); } public static Seq seq(ElementNode[] elements) { return new Seq(elements); } public static @bind.as("Elements") Seq seq2(ElementNode[] elements) { return new Seq(elements); } public static @bind.as Seq psx(Seq s) { return s; } public static @bind.as(":") ElementNode colon(String s, ElementNode e) { return new Label(s, e); } public static @bind.as(")") void close(String foo) { throw new Error("not supported"); } - public static @bind.as("()") ElementNode epsilon() { return new Constant(Union.epsilon); } + public static @bind.as("()") ElementNode epsilon() { return new Constant(epsilon); } + + private static Union epsilon = new Union("()"); + static { epsilon.add(Sequence.empty); } public static class NonTerminalReferenceNode extends ElementNode { public String nonTerminal; @@ -289,6 +290,9 @@ public class MetaGrammarBindings { public @bind.as("NonTerminalReference") NonTerminalReferenceNode(String nonTerminal) { this.nonTerminal = prefix + nonTerminal; } + public Atom toAtom(Context cx) { + return cx.grammar.get(nonTerminal).toAtom(cx); + } public Element build(Context cx, NonTerminalNode cnt) { if (!this.nonTerminal.startsWith(prefix)) nonTerminal = prefix + nonTerminal; Element ret = cx.get(nonTerminal); @@ -298,33 +302,49 @@ public class MetaGrammarBindings { } public static class Literal extends Constant { - public @bind Literal(@bind.arg String string) { super(CharRange.string(string)); } + private String string; + public @bind Literal(@bind.arg String string) { + super(CharAtom.string(string)); + this.string = string; + } public boolean drop() { 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(); + set.add(string.charAt(0), string.charAt(0)); + return CharAtom.set(set); + } } public static class CharClass extends ElementNode { Range[] ranges; public @bind.as("[") CharClass(Range[] ranges) { this.ranges = ranges; } + public Atom toAtom(Context cx) { + edu.berkeley.sbp.util.Range.Set set = new edu.berkeley.sbp.util.Range.Set(); + for(Range r : ranges) + set.add(r.first, r.last); + return CharAtom.set(set); + } public Element build(Context cx, NonTerminalNode cnt) { edu.berkeley.sbp.util.Range.Set set = new edu.berkeley.sbp.util.Range.Set(); for(Range r : ranges) set.add(r.first, r.last); - return CharRange.set(set); + return CharAtom.set(set); } } public static @bind.as("{") class XTree extends ElementNode { public @bind.arg Seq body; public Element build(Context cx, NonTerminalNode cnt) { - Union u = new Union(); + Union u = new Union(null, false); Sequence s = body.build(cx, u, false, null); - Union u2 = new Union(); + Union u2 = new Union(null, false); u2.add(Sequence.singleton(new Element[] { - CharRange.leftBrace, + CharAtom.leftBrace, cx.get("ws"), u, cx.get("ws"), - CharRange.rightBrace + CharAtom.rightBrace }, 2)); return u2; } @@ -335,25 +355,18 @@ public class MetaGrammarBindings { public boolean zero, many, max; public Rep(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;} + public Atom toAtom(Context cx) { + if (sep != null) return super.toAtom(cx); + return e.toAtom(cx); + } public Element build(Context cx, NonTerminalNode cnt) { return (!max) - ? Sequence.repeat(e.build(cx, null), zero, many, sep==null ? null : sep.build(cx, null), cx.rm.repeatTag()) + ? Sequence.repeat(e.build(cx, null), zero, many, sep==null ? null : sep.build(cx, null), cx.rm.repeatTag()) : sep==null - ? Sequence.repeatMaximal(infer(e.build(cx, null)), zero, many, cx.rm.repeatTag()) - : Sequence.repeatMaximal(e.build(cx, null), zero, many, infer(sep.build(cx, null)), cx.rm.repeatTag()); + ? Sequence.repeatMaximal(e.toAtom(cx), zero, many, cx.rm.repeatTag()) + : Sequence.repeatMaximal(e.build(cx, null), zero, many, sep.toAtom(cx), cx.rm.repeatTag()); } } - public static class Constant extends ElementNode { - Element constant; - public Constant(Element constant) { this.constant = constant; } - public Element build(Context cx, NonTerminalNode cnt) { return constant; } - } - public abstract static class PostProcess extends ElementNode { - ElementNode e; - public PostProcess(ElementNode e) { this.e = e; } - public Element build(Context cx, NonTerminalNode cnt) { return postProcess(e.build(cx, cnt)); } - public abstract Element postProcess(Element e); - } // FIXME: it would be nice if we could hoist this into "Rep" public static @bind.as("++") ElementNode plusmax(final ElementNode e) @@ -378,15 +391,20 @@ public class MetaGrammarBindings { { return new Drop(e); } public static @bind.as("^") ElementNode caret(final String s) { - return new Drop(new Constant(CharRange.string(s)) { - public String getOwnerTag() { return s; } - }); + final String thePrefix = prefix; + return new Constant(CharAtom.string(s)) { + public String getOwnerTag() { return thePrefix+s; } + public boolean drop() { return true; } + }; } public static @bind.as("~") ElementNode tilde(final ElementNode e) { - return new PostProcess(e) { - public Element postProcess(Element e) { - return infer((Topology)Atom.toAtom(e).complement().minus(CharRange.braces)); + return new ElementNodeWrapper(e) { + public Atom toAtom(Context cx) { + return infer((Topology)e.toAtom(cx).complement().minus(CharAtom.braces)); + } + public Element build(Context cx, NonTerminalNode cnt) { + return infer((Topology)e.toAtom(cx).complement().minus(CharAtom.braces)); } }; } public static @bind.as("Word") String word(String s) { return s; } @@ -396,15 +414,15 @@ public class MetaGrammarBindings { public static @bind.as("\n") String retur() { return "\n"; } public static @bind.as("\r") String lf() { return "\r"; } - static Atom infer(Element e) { return infer((Topology)Atom.toAtom(e)); } - static Atom infer(Topology t) { return new CharRange(new CharTopology(t)); } + //static Atom infer(Element e) { return infer((Topology)Atom.toAtom(e)); } + static Atom infer(Topology t) { return new CharAtom(new CharTopology(t)); } public static class Context { public HashMap map = new HashMap(); public GrammarNode grammar; public String cnt = null; - public GrammarBindingResolver rm; - public Context(GrammarNode g, GrammarBindingResolver rm) { + public Grammar.Bindings rm; + public Context(GrammarNode g, Grammar.Bindings rm) { this.grammar = g; this.rm = rm; } @@ -417,9 +435,9 @@ public class MetaGrammarBindings { } return ret; } - public Context(Tree t, GrammarBindingResolver rm) { + public Context(Tree t, Grammar.Bindings rm) { this.rm = rm; - Tree.TreeFunctor red = (Tree.TreeFunctor)t.head(); + TreeFunctor red = (TreeFunctor)t.head(); this.grammar = (GrammarNode)red.invoke(t); } public Union peek(String name) { return map.get(name); } @@ -431,7 +449,6 @@ public class MetaGrammarBindings { map.put(name, ret); NonTerminalNode nt = grammar.get(name); if (nt==null) { - //System.err.println("*** warning could not find " + name); throw new Error("warning could not find " + name); } else { String old = cnt; @@ -444,4 +461,55 @@ public class MetaGrammarBindings { } + public static abstract class ElementNode { + public String getLabel() { return null; } + public String getOwnerTag() { return null; } + public boolean drop() { return false; } + public Atom toAtom(Context cx) { throw new Error("can't convert a " + this.getClass().getName() + " to an atom"); } + public abstract Element build(Context cx, NonTerminalNode cnt); + } + + public static abstract class ElementNodeWrapper extends ElementNode { + protected ElementNode _e; + public ElementNodeWrapper(ElementNode e) { this._e = e; } + public String getLabel() { return _e.getLabel(); } + public String getOwnerTag() { return _e.getOwnerTag(); } + public boolean drop() { return _e.drop(); } + public Atom toAtom(Context cx) { return _e.toAtom(cx); } + public Element build(Context cx, NonTerminalNode cnt) { return _e.build(cx, cnt); } + } + + public static class Constant extends ElementNode { + Element constant; + public Constant(Element constant) { this.constant = constant; } + public Element build(Context cx, NonTerminalNode cnt) { return constant; } + public Atom toAtom(Context cx) { + if (constant instanceof Atom) return ((Atom)constant); + return super.toAtom(cx); + } + } + + public abstract static class PostProcess extends ElementNodeWrapper { + public PostProcess(ElementNode e) { super(e); } + public Element build(Context cx, NonTerminalNode cnt) { return postProcess(_e.build(cx, cnt)); } + public abstract Element postProcess(Element e); + } + + public static class Drop extends ElementNodeWrapper { + public Drop(ElementNode e) { super(e); } + public boolean drop() { return true; } + } + + public static class Label extends ElementNodeWrapper { + public String label; + public Label(String label, ElementNode e) { super(e); this.label = label; } + public String getLabel() { return label; } + } + + static class Invert extends Atom { + private final Atom a; + public Invert(Atom a) { this.a = a; } + public Topology top() { return a.complement(); } + public String toString() { return "~"+a; } + } }