X-Git-Url: http://git.megacz.com/?p=sbp.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fsbp%2Fmisc%2FMetaGrammar.java;fp=src%2Fedu%2Fberkeley%2Fsbp%2Fmisc%2FMetaGrammar.java;h=eacdcf640d6234db688c65266d083bd43c4fb0ab;hp=1f7718faa66ae06da91a2d39de72a2342ba0ef71;hb=1a318fea23d4802f8413bff48fe9d26809fb61f9;hpb=8abe88ea7a5d7b1fc20c45b05e6397dad81e7cdb diff --git a/src/edu/berkeley/sbp/misc/MetaGrammar.java b/src/edu/berkeley/sbp/misc/MetaGrammar.java index 1f7718f..eacdcf6 100644 --- a/src/edu/berkeley/sbp/misc/MetaGrammar.java +++ b/src/edu/berkeley/sbp/misc/MetaGrammar.java @@ -2,462 +2,638 @@ package edu.berkeley.sbp.misc; import edu.berkeley.sbp.util.*; import edu.berkeley.sbp.*; import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.bind.*; import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; import java.io.*; -public class MetaGrammar extends StringWalker { +public class MetaGrammar { + + public static boolean harsh = false; - public static Union make() throws Exception { return make(MetaGrammarTree.meta, "s"); } - public static Union make(Tree tree, String nt) throws Exception { - Meta.MetaGrammarFile mgf = new Meta().new MetaGrammarFile(tree); - BuildContext bc = new BuildContext(mgf); - return mgf.get(nt).build(bc); - } + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println("usage: java " + MetaGrammar.class.getName() + " grammarfile.g com.yourdomain.package.ClassName"); + System.exit(-1); + } + //StringBuffer sbs = new StringBuffer(); + //((MetaGrammar)new MetaGrammar().walk(meta)).nt.get("e").toString(sbs); + //System.err.println(sbs); + String className = args[1].substring(args[1].lastIndexOf('.')+1); + String packageName = args[1].substring(0, args[1].lastIndexOf('.')); + String fileName = packageName.replace('.', '/') + "/" + className + ".java"; - //////////////////////////////////////////////////////////////////////////////// + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); + StringBuffer out = new StringBuffer(); - private static Element set(Range.Set r) { return CharRange.set(r); } - private static Element string(String s) { return CharRange.string(s); } - /*private*/ static Atom infer(Element e) { return infer((Topology)Atom.toAtom(e)); } - /*private*/ static Atom infer(Topology t) { return new CharRange(new CharTopology(t)); } + boolean skip = false; + for(String s = br.readLine(); s != null; s = br.readLine()) { + if (s.indexOf("DO NOT EDIT STUFF BELOW: IT IS AUTOMATICALLY GENERATED") != -1 && s.indexOf("\"")==-1) skip = true; + if (s.indexOf("DO NOT EDIT STUFF ABOVE: IT IS AUTOMATICALLY GENERATED") != -1 && s.indexOf("\"")==-1) break; + if (!skip) out.append(s+"\n"); + } + + out.append("\n // DO NOT EDIT STUFF BELOW: IT IS AUTOMATICALLY GENERATED\n"); + + /* + ReflectiveMeta m = new ReflectiveMeta(); + Tree res = new CharParser(MetaGrammar.make()).parse(new FileInputStream(args[0])).expand1(); + MetaGrammar.Meta.MetaGrammarFile mgf = m.new MetaGrammarFile(res); + MetaGrammar.BuildContext bc = new MetaGrammar.BuildContext(mgf); - private MetaGrammar() { } + Union meta = mgf.get("s").build(bc); + Tree t = new CharParser(meta).parse(new FileInputStream(args[0])).expand1(); + */ + Tree t = MetaGrammarTree.meta; + Union u = MetaGrammar.make(t, "s"); - public static String string(Iterable> children) { - String ret = ""; - for(Tree t : children) ret += string(t); - return ret; + System.err.println(); + System.err.println("== parsing with parsed grammar ================================================================================="); + t = new CharParser((Union)u).parse(new FileInputStream(args[0])).expand1(); + System.out.println(t.toPrettyString()); + //Forest fs = new CharParser(make()).parse(new FileInputStream(args[0])); + //System.out.println(fs.expand1()); + + //GraphViz gv = new GraphViz(); + //fs.toGraphViz(gv); + //FileOutputStream fox = new FileOutputStream("out.dot"); + //gv.dump(fox); + //fox.close(); + + t.toJava(out); + out.append("\n // DO NOT EDIT STUFF ABOVE: IT IS AUTOMATICALLY GENERATED\n"); + + for(String s = br.readLine(); s != null; s = br.readLine()) out.append(s+"\n"); + br.close(); + + OutputStream os = new FileOutputStream(fileName); + PrintWriter p = new PrintWriter(new OutputStreamWriter(os)); + p.println(out.toString()); + p.flush(); + os.close(); } - public static String string(Tree tree) { - String ret = ""; - if (tree.head()!=null) ret += tree.head(); - ret += string(tree.children()); - return ret; + + public static class ReflectiveMetaPlain extends ReflectiveMeta { + public Object repeatTag() { return null; } + public Sequence tryResolveTag(String tag, String nonTerminalName, Element[] els, Object[] labels, boolean[] drops) { + return null; } + public Sequence resolveTag(String tag, String nonTerminalName, Element[] els, Object[] labels, boolean[] drops) { + return Sequence.rewritingSequence(tag, els, labels, drops); + } } - public static class BuildContext extends HashMap { - private final Meta.MetaGrammarFile mgf; - public Meta.NonTerminal currentNonTerminal; - public BuildContext(Meta.MetaGrammarFile mgf) { this.mgf = mgf; } - public Union build(String s) { - Union ret = get(s); + public static class ReflectiveMeta /*extends MetaGrammar.Meta*/ { + private final Class _cl; + private final Class[] _inner; + public ReflectiveMeta() { + this(MG.class); + } + public ReflectiveMeta(Class c) { + this._cl = c; + this._inner = c.getDeclaredClasses(); + } + public ReflectiveMeta(Class c, Class[] inner) { + this._cl = c; + this._inner = inner; + } + private boolean match(Method m, String s) { return match(m.getAnnotation(bind.as.class), null, s); } + private boolean match(bind.as t, Class c, String s) { + if (t==null) return false; + if (t.value().equals(s)) return true; + if (c != null && t.equals("") && c.getSimpleName().equals(s)) return true; + return false; + } + /* + private boolean match(nonterminal t, Class c, String s) { + if (t==null) return false; + if (t.value().equals(s)) return true; + if (c != null && t.equals("") && c.getSimpleName().equals(s)) return true; + return false; + } + */ + private boolean match(Class c, String s, String nonTerminalName) { + if (match((bind.as)c.getAnnotation(bind.as.class), c, s)) return true; + //if (match((nonterminal)c.getAnnotation(bind.as.class), c, nonTerminalName)) return true; + return false; + } + public boolean match(Constructor con, String s, String nonTerminalName) { + Class c = con.getDeclaringClass(); + if (match((bind.as)con.getAnnotation(bind.as.class), null, s)) return true; + //if (match((nonterminal)con.getAnnotation(bind.as.class), c, s)) return true; + return false; + } + public Object repeatTag() { + return new Tree.ArrayBuildingTreeFunctor(); + } + public Sequence tryResolveTag(String tag, String nonTerminalName, Element[] els, Object[] labels, boolean[] drops) { + Production p = new Production(tag, nonTerminalName, els, labels, drops); + for(Method m : _cl.getMethods()) + if (new Target(m).isCompatible(p)) + return new Target(m).makeSequence(p); + for(Class c : _inner) + for(Constructor con : c.getConstructors()) + if (new Target(con).isCompatible(p)) + return new Target(con).makeSequence(p); + for(Class c : _inner) + if (new Target(c).isCompatible(p)) + return new Target(c).makeSequence(p); + return null; + } + public Sequence resolveTag(String tag, String nonTerminalName, Element[] els, Object[] labels, boolean[] drops) { + Sequence ret = tryResolveTag(tag, nonTerminalName, els, labels, drops); if (ret != null) return ret; - Meta.NonTerminal mnt = mgf.get(s); - if (mnt==null) throw new Error("undeclared nonterminal \""+s+"\""); - return mnt.build(this); + String message = "could not find a Java method/class/ctor matching tag \""+tag+ + "\", nonterminal \""+nonTerminalName+"\" with " + els.length + " arguments"; + if (harsh) { + throw new RuntimeException(message); + } else { + System.err.println(message); + return Sequence.rewritingSequence(tag, els, labels, drops); + } } } - public static class Meta { - public Object repeatTag() { return null; } - public Sequence tryResolveTag(String s, String nonTerminalName, Element[] els, Object[] labels, boolean [] drops) { - //return resolveTag(s, nonTerminalName, els, labels, drops); - return null; + + public static class Production { + public String tag; + public String nonTerminal; + public Object[] labels; + public boolean[] drops; + public Element[] elements; + public int count = 0; + public Production(String tag, String nonTerminal, Element[] elements, Object[] labels, boolean[] drops) { + this.tag = tag; + this.elements = elements; + this.nonTerminal = nonTerminal; + this.labels = labels; + this.drops = drops; + for(int i=0; i { - public MetaGrammarFile(Tree tree) { - if (!tree.head().equals("grammar")) throw new Error(); - for(Tree nt : tree.child(0)) - add(new NonTerminal(nt)); - } - private void add(NonTerminal mnt) { - if (this.get(mnt.name)!=null) throw new Error("duplicate definition of nonterminal \""+mnt.name+"\""); - this.put(mnt.name, mnt); - } - public String toString() { - String ret = ""; - for(NonTerminal mnt : this.values()) ret += mnt + "\n"; + private Bindable _bindable; + + public Target(Object o) { this(Bindable.create(o)); } + public Target(Bindable b) { this._bindable = b; } + + public String getName() { return _bindable.getSimpleName(); } + public bind.as getBindAs() { return (bind.as)_bindable.getAnnotation(bind.as.class); } + //public nonterminal getNonTerminal() { return (nonterminal)_bindable.getAnnotation(bind.as.class); } + public String toString() { return _bindable.getSimpleName(); } + public boolean isRaw() { return _bindable.isAnnotationPresent(bind.raw.class); } + + public boolean isCompatible(Production p) { + bind.as t = getBindAs(); + if (t != null && + (t.value().equals(p.tag) || + (t.value().equals("") && getName().equals(p.tag)))) + return buildSequence(p)!=null; + + bind.as n = getBindAs(); + if (n != null && + (n.value().equals(p.nonTerminal) || + (n.value().equals("") && getName().equals(p.nonTerminal)))) + return buildSequence(p)!=null; + + return false; + } + + public int[] buildSequence(Production p, String[] names, bind.arg[] argtags) { + int argTagged = 0; + for(int i=0; i tree) { - name = string(tree.child(0)); - rhs = rhs(tree.child(1)); - } - public String toString() { return name + " = " + rhs; } - public Union build(BuildContext bc) { - NonTerminal ont = bc.currentNonTerminal; - bc.currentNonTerminal = this; - try { - return rhs.build(bc, name); - } finally { - bc.currentNonTerminal = ont; + public Sequence makeSequence(Production p) { + return Sequence.rewritingSequence(new TargetReducer(buildSequence(p), _bindable, isRaw()), + p.elements, p.labels, p.drops); + } + + } + + public static class TargetReducer implements Tree.TreeFunctor, ToJava { + private int[] map; + private Bindable _bindable; + private boolean _israw; + + public void toJava(StringBuffer sb) { + sb.append("new MetaGrammar.TargetReducer(new int[] {"); + for(int i=0; i> t) { + if (_israw) return _bindable.impose(new Object[] { t }); + ArrayList ret = new ArrayList(); + for(Tree tc : t) { + if (tc.head() != null && tc.head() instanceof Functor) + ret.add(((Tree.TreeFunctor)tc.head()).invoke(tc.children())); + else if (tc.numChildren() == 0) + ret.add(tc.head()); + else { + System.err.println("FIXME: don't know what to do about " + tc); + ret.add(null); } } + System.err.println("input tree: " + t); + Object[] o = (Object[])ret.toArray(new Object[0]); + int max = 0; + for(int i=0; i res = new CharParser(MetaGrammar.make()).parse(new FileInputStream("tests/meta.g")).expand1(); + MetaGrammar.Meta.MetaGrammarFile mgf = m.new MetaGrammarFile(res); + MetaGrammar.BuildContext bc = new MetaGrammar.BuildContext(mgf); + Union meta = mgf.get("s").build(bc); + Tree t = new CharParser(meta).parse(new FileInputStream("tests/meta.g")).expand1(); + return cached = make(t, "s"); + } catch (Exception e) { + throw new RuntimeException(e); } - public MetaUnion rhs(Tree t) { - return t.numChildren()==1 - ? new MetaUnion(t.child(0), false) - : new MetaUnion(t, true); + */ + return make(MetaGrammarTree.meta, "s"); + } + public static Union make(Tree t, String s) { return make(t, s, new ReflectiveMeta()); } + public static Union make(Tree t, String s, ReflectiveMeta rm) { + Tree.TreeFunctor red = (Tree.TreeFunctor)t.head(); + MG.Grammar g = (MG.Grammar)red.invoke(t.children()); + Context cx = new Context(g,rm); + Union u = null; + for(MG.NonTerminal nt : g.nonterminals) { + System.out.println(nt.name); + Union el = (Union)cx.get(nt.name); + StringBuffer st = new StringBuffer(); + el.toString(st); + System.err.println(st); + if (nt.name.equals(s)) u = el; } - public class MetaUnion implements MetaSequence { - public boolean prioritized; - public MetaSequence[] sequences; - public Sequence buildSequence(BuildContext bc) { - return Sequence.singleton(new Element[] { buildAnon(bc) }, 0); + return u; + } + + + + public static class MG { + public static @bind.as("grammar") class Grammar { + public NonTerminal get(String s) { + for(NonTerminal nt : nonterminals) + if (nt.name.equals(s)) + return nt; + return null; } - public Union buildAnon(BuildContext bc) { - String s = ""; - for(int i=0; i0?"\n "+(prioritized?">":"|")+" ":"")+sequences[i].buildSequence(bc); - return build(bc, s); + public @bind.arg("NonTerminal") NonTerminal[] nonterminals; + public String toString() { + String ret = "[ "; + for(NonTerminal nt : nonterminals) ret += nt + ", "; + return ret + " ]"; } - public Union build(BuildContext bc, String name) { - Union u = bc.get(name); - if (u != null) return u; - u = new Union(name); - bc.put(name, u); - HashSet seqs = new HashSet(); - for(MetaSequence s : sequences) { - Sequence seq = s.buildSequence(bc); - if (seq != null) { - Sequence oseq = seq; - if (prioritized) - for(Sequence seqprev : seqs) - seq = seq.not(seqprev); - u.add(seq); - seqs.add(seq); + } + public abstract static class Un extends El { + public Seq[][] sequences; + public void build(Context cx, Union u) { + HashSet bad2 = new HashSet(); + for(int i=0; i t, boolean prioritized) { - this.prioritized = prioritized; - int i = 0; - this.sequences = new MetaSequence[t.numChildren()]; - for(Tree tt : t) - sequences[i++] = prioritized - ? new MetaUnion(tt, false) - : makeMetaSequence(tt); + } + public static class NonTerminal extends Un { + public String name = null; + public @bind.as("=") NonTerminal(@bind.arg("Word") String name, + @bind.arg("RHS") Seq[][] sequences) { + this.name = name; + this.sequences = sequences; } - public String toString() { - String ret = "\n "; - for(int i=0; i " : "\n | "); - } + public Element build(Context cx) { return cx.get(name); } + } + + public static class AnonUn extends Un { + public @bind.as("(") AnonUn(Seq[][] sequences) { + this.sequences = sequences; + } + public Element build(Context cx) { + Union ret = new Union(); + build(cx, ret); return ret; } } - public interface MetaSequence { - public abstract Sequence buildSequence(BuildContext bc); + //public static @bind.as void range(char c) { } + public static class Range { + public @bind.as("range") Range(char only) { first = only; last = only; } + public @bind.as("-") Range(char first, char last) { this.first = first; this.last = last; } + public char first; + public char last; } - - public MetaSequence makeMetaSequence(Tree t) { - if ("psx".equals(t.head())) return makeConjunct(t.child(0)); - if (t.head().equals("&")) return new MetaAnd(makeMetaSequence(t.child(0)), makeConjunct(t.child(1)), false); - if (t.head().equals("&~")) return new MetaAnd(makeMetaSequence(t.child(0)), makeConjunct(t.child(1)), true); - return null; + public static abstract class El { + public String getLabel() { return null; } + public String getOwnerTag() { return null; } + public boolean drop() { return false; } + public abstract Element build(Context cx); } - - public class MetaAnd implements MetaSequence { - boolean not; - MetaSequence left; - MetaSequence right; - public Sequence buildSequence(BuildContext bc) { - Union u = new Union(toString()); - Sequence ret = left.buildSequence(bc); - Sequence rs = right.buildSequence(bc); - rs.lame = true; - if (not) ret = ret.not(rs); - else ret = ret.and(rs); - u.add(rs); - u.add(ret); - return Sequence.singleton(u); + public static class Drop extends El { + public El e; + public Drop(El e) { this.e = e; } + public String getLabel() { return null; } + public boolean drop() { return true; } + public String getOwnerTag() { return e.getOwnerTag(); } + public Element build(Context cx) { return e.build(cx); } + } + public static class Label extends El { + public String label; + public El e; + public Label(String label, El e) { this.e = e; this.label = label; } + public String getLabel() { return label; } + public String getOwnerTag() { return e.getOwnerTag(); } + public Element build(Context cx) { return e.build(cx); } + } + public static /*abstract*/ class Seq { + HashSet and = new HashSet(); + HashSet not = new HashSet(); + El[] elements; + El follow; + String tag = null; + boolean lame; + public Seq(El e) { this(new El[] { e }); } + public Seq(El[] elements) { this.elements = elements; } + public Seq tag(String tag) { this.tag = tag; return this; } + public Seq follow(El 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; + return ret; } - public MetaAnd(MetaSequence left, MetaSequence right, boolean not) { - this.left = left; - this.right = right; - this.not = not; + public Seq and(Seq s) { and.add(s); s.lame = true; return this; } + public Seq andnot(Seq s) { not.add(s); s.lame = true; return this; } + public Seq separate(El sep) { + El[] elements = new El[this.elements.length * 2 - 1]; + for(int i=0; i labelMap = new HashMap(); - public MetaClause followedBy = null; - public String tag; - public MetaClause separator; - public void addNamedClause(String name, MetaClause mc) { - labelMap.put(mc, name); + public Sequence build(Context cx, Union u, boolean lame) { + Sequence ret = build0(cx, lame || this.lame); + for(Seq s : and) { Sequence dork = s.build(cx, u, true); ret = ret.and(dork); } + for(Seq s : not) { Sequence dork = s.build(cx, u, true); ret = ret.not(dork); } + u.add(ret); + ret.lame = lame; + return ret; } - public Sequence buildSequence(BuildContext bc) { - Element[] els = new Element[elements.length + (separator==null?0:(elements.length-1))]; - boolean[] drops = new boolean[elements.length + (separator==null?0:(elements.length-1))]; - Object[] labels = new Object[els.length]; + public Sequence build0(Context cx, boolean lame) { boolean unwrap = false; - boolean dropAll = false; - if (tag!=null && tag.equals("[]")) unwrap = true; - if (tag!=null && "()".equals(tag)) dropAll=true; - - NonTerminal old = bc.currentNonTerminal; - bc.currentNonTerminal = null; + boolean dropAll = lame; + if (tag!=null && tag.equals("[]")) unwrap = true; + if (tag!=null && "()".equals(tag)) dropAll = true; + Object[] labels = new Object[elements.length]; + boolean[] drops = new boolean[elements.length]; + Element[] els = new Element[elements.length]; for(int i=0; i " + ret); + ret = cx.rm.resolveTag(tag, cx.cnt, els, labels, drops); } else { - ret = tryResolveTag(tag, bc.currentNonTerminal==null ? null : bc.currentNonTerminal.name, els, labels, drops); - if (ret==null) { - int idx = -1; - for(int i=0; i t) { - elements = new MetaClause[t.numChildren()]; - int i = 0; for(Tree tt : t) - elements[i++] = makeMetaClause(tt, this); - } - public String toString() { - String ret = (tag==null ? "" : (tag+":: ")) + (negated ? "~" : ""); - if (elements.length > 1) ret += "("; - for(MetaClause mc : elements) ret += (" " + mc + " "); - if (separator != null) ret += " /" + separator; - if (followedBy != null) ret += " -> " + followedBy; - if (elements.length > 1) ret += ")"; + if (this.follow != null) + ret.follow = infer(this.follow.build(cx)); + ret.lame = this.lame; return ret; } } - public Conjunct makeConjunct(Tree t) { - //System.err.println("makeConjunct("+t+")"); - if ("/".equals(t.head())) { - Conjunct ret = makeConjunct(t.child(0)); - ret.separator = makeMetaClause(t.child(1), ret); - return ret; - } - if ("->".equals(t.head())) { - Conjunct ret = makeConjunct(t.child(0)); - ret.followedBy = makeMetaClause(t.child(1), ret); - return ret; - } - if ("::".equals(t.head())) { - Conjunct ret = makeConjunct(t.child(1)); - ret.tag = string(t.child(0)); - return ret; - } - if ("ps".equals(t.head())) { - return new Conjunct(t.child(0)); - } - return new Conjunct(t); - } + public static @bind.as("&") Seq and(Seq s, El[] elements) { return s.and(seq(elements)); } + public static @bind.as("&~") Seq andnot(Seq s, El[] elements) { return s.andnot(seq(elements)); } + public static @bind.as("->") Seq arrow(Seq s, El 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, El e) { return s.separate(e); } - public MetaClause makeMetaClause(Tree t, Conjunct c) { - //System.err.println("MetaClause.makeMetaClause("+t+")"); - if (t==null) return new Epsilon(); - if (t.head()==null) return new Epsilon(); - if (t.head().equals("{")) return new MetaTree(makeConjunct(t.child(0))); - if (t.head().equals("*")) return new MetaRepeat(makeMetaClause(t.child(0), c), false, null, true, true); - if (t.head().equals("+")) return new MetaRepeat(makeMetaClause(t.child(0), c), false, null, false, true); - if (t.head().equals("?")) return new MetaRepeat(makeMetaClause(t.child(0), c), false, null, true, false); - if (t.head().equals("**")) return new MetaRepeat(makeMetaClause(t.child(0), c), true, null, true, true); - if (t.head().equals("++")) return new MetaRepeat(makeMetaClause(t.child(0), c), true, null, false, true); - if (t.head().equals("*/")) return new MetaRepeat(makeMetaClause(t.child(0), c), false, makeMetaClause(t.child(1), c), true, true); - if (t.head().equals("+/")) return new MetaRepeat(makeMetaClause(t.child(0), c), false, makeMetaClause(t.child(1), c), false, true); - if (t.head().equals("**/")) return new MetaRepeat(makeMetaClause(t.child(0), c), true, makeMetaClause(t.child(1), c), true, true); - if (t.head().equals("++/")) return new MetaRepeat(makeMetaClause(t.child(0), c), true, makeMetaClause(t.child(1), c), false, true); - if (t.head().equals("()")) return new Epsilon(); - if (t.head().equals("[")) return new MetaRange(t.child(0)); - if (t.head().equals("literal")) return new StringLiteral(t.child(0)); - if (t.head().equals("nonTerminal")) return new NonTerminalReference(t.child(0)); - if (t.head().equals(")")) return new SelfReference(); - if (t.head().equals("(")) return new Parens(t.child(0)); - if (t.head().equals("~")) return new MetaInvert(t.child(0), c); - if (t.head().equals("!")) { MetaClause mc = makeMetaClause(t.child(0), c); mc.drop = true; return mc; } - if (t.head().equals("^")) { c.tag = string(t.child(0)); return new StringLiteral(t.child(0)); } - if (t.head().equals("^^")) throw new Error("carets: " + t); - if (t.head().equals(":")) { - String name = string(t.child(0)); - MetaClause clause = makeMetaClause(t.child(1), c); - c.addNamedClause(name, clause); - return clause; - } - throw new Error("unknown: " + t); - } + public static @bind.as("ps") Seq seq(El[] elements) { return new Seq(elements); } + public static @bind.as Seq psx(Seq s) { return s; } + public static @bind.as(":") El colon(String s, El e) { return new Label(s, e); } + public static @bind.as(")") void close(String foo) { throw new Error("not supported"); } + public static @bind.as("()") El epsilon() { return new Constant(Union.epsilon); } - public abstract class MetaClause { - public String label = null; - public boolean drop = false; - public boolean lift = false; - public abstract Element build(BuildContext bc); - } - public class MetaRepeat extends MetaClause { - public MetaClause element, separator; - public boolean maximal, zero, many; - public Element build(BuildContext bc) { - return !maximal - ? (separator==null - ? Sequence.repeat(element.build(bc), zero, many, null, repeatTag()) - : Sequence.repeat(element.build(bc), zero, many, separator.build(bc), repeatTag())) - : (separator==null - ? Sequence.repeatMaximal(infer(element.build(bc)), zero, many, repeatTag()) - : Sequence.repeatMaximal(element.build(bc), zero, many, infer(separator.build(bc)), repeatTag())); - } - public MetaRepeat(MetaClause element, boolean maximal, MetaClause separator, boolean zero, boolean many) { - this.separator = separator; - this.element = element; - this.maximal = maximal; - this.zero = zero; - this.many = many; - } - public String toString() { - return element+ - ((zero&&!many)?"?":zero?"*":"+")+ - (!maximal?"":zero?"*":"+")+ - (separator==null?"":(" /"+separator)); - } - } - public class Epsilon extends MetaClause { - public String toString() { return "()"; } - public Element build(BuildContext bc) { return Union.epsilon; } - } - public class Parens extends MetaClause { - public MetaUnion body; - public Parens(Tree t) { this.body = rhs(t); } - public String toString() { return "( " + body + " )"; } - public Element build(BuildContext bc) { return body.buildAnon(bc); } + public static @bind.as("nonTerminal") class NonTerminalReference extends El { + public @bind.arg String nonTerminal; + public Element build(Context cx) { + return cx.get(nonTerminal); } + } - public class MetaTree extends MetaClause { - public Conjunct body; - public MetaTree(Conjunct c) { this.body = c; } - public String toString() { return "{ " + body + " }"; } - public Element build(BuildContext bc) { - Union u = new Union(); - Union u2 = new Union(); - Sequence seq = body.buildSequence(bc); - u2.add(seq); - u.add(Sequence.singleton(new Element[] { CharRange.leftBrace, - new NonTerminalReference("ws").build(bc), - u2, - new NonTerminalReference("ws").build(bc), - CharRange.rightBrace } - , 2)); - //u.add(seq); - return u; - } - } + public static class StringLiteral extends Constant { + public @bind.as("literal") StringLiteral(String string) { super(CharRange.string(string)); } + public boolean drop() { return true; } + } - public class MetaRange extends MetaClause { - Range.Set range = new Range.Set(); - public String toString() { return range.toString(); } - public Element build(BuildContext bc) { return set(range); } - public MetaRange(Tree t) { - for(Tree tt : t) { - if (tt.head().equals("range")) { - range.add(tt.child(0).head().charAt(0)); - } else if (tt.head().equals("-")) { - range.add(new Range(string(tt.child(0)).charAt(0), - string(tt.child(1)).charAt(0))); - } - } - } - } - public class StringLiteral extends MetaClause { - public String literal; - public Element build(BuildContext bc) { return string(literal); } - public StringLiteral(Tree literal) { this.literal = string(literal); this.drop = true; } - public String toString() { return "\""+StringUtil.escapify(literal, "\"\r\n\\")+"\""; } - } - public class NonTerminalReference extends MetaClause { - public String name; - public NonTerminalReference(Tree name) { this.name = string(name); } - public NonTerminalReference(String name) { this.name = name; } - public Element build(BuildContext bc) { return bc.build(name); } - public String toString() { return name; } - } - public class SelfReference extends MetaClause { - public String toString() { return "(*)"; } - public Element build(BuildContext bc) { return new Union("(*)"); /* FIXME */ } - } - public class MetaInvert extends MetaClause { - public MetaClause element; - public MetaInvert(Tree t, Conjunct c) { this.element = makeMetaClause(t, c); } - public String toString() { return "~"+element; } - public Element build(BuildContext bc) { - return infer((Topology)Atom.toAtom(element.build(bc)).complement().minus(CharRange.braces)); - } + public static class CharClass extends El { + Range[] ranges; + public @bind.as("[") CharClass(Range[] ranges) { this.ranges = ranges; } + public Element build(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 CharRange.set(set); } + } - } + public static @bind.as("{") class XTree extends El { + public @bind.arg Seq body; + public Element build(Context cx) { + throw new Error(); + } + } - public static void main(String[] args) throws Exception { - if (args.length != 2) { - System.err.println("usage: java " + MetaGrammar.class.getName() + " grammarfile.g com.yourdomain.package.ClassName"); - System.exit(-1); + public static class Rep extends El { + public El e, sep; + public boolean zero, many, max; + public Rep(El e, El sep, boolean zero, boolean many, boolean max) { + this.e = e; this.sep = sep; this.zero = zero; this.many = many; this.max = max;} + public Element build(Context cx) { + return (!max) + ? Sequence.repeat(e.build(cx), zero, many, sep==null ? null : sep.build(cx), cx.rm.repeatTag()) + : sep==null + ? Sequence.repeatMaximal(infer(e.build(cx)), zero, many, cx.rm.repeatTag()) + : Sequence.repeatMaximal(e.build(cx), zero, many, infer(sep.build(cx)), cx.rm.repeatTag()); + } + } + public static class Constant extends El { + Element constant; + public Constant(Element constant) { this.constant = constant; } + public Element build(Context cx) { return constant; } + } + public abstract static class PostProcess extends El { + El e; + public PostProcess(El e) { this.e = e; } + public Element build(Context cx) { return postProcess(e.build(cx)); } + public abstract Element postProcess(Element e); } - //StringBuffer sbs = new StringBuffer(); - //((MetaGrammar)new MetaGrammar().walk(meta)).nt.get("e").toString(sbs); - //System.err.println(sbs); - String className = args[1].substring(args[1].lastIndexOf('.')+1); - String packageName = args[1].substring(0, args[1].lastIndexOf('.')); - String fileName = packageName.replace('.', '/') + "/" + className + ".java"; - BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); - StringBuffer out = new StringBuffer(); + // FIXME: it would be nice if we could hoist this into "Rep" + public static @bind.as("++") El plusmax(final El e) { return new Rep(e, null, false, true, true); } + public static @bind.as("+") El plus(final El e) { return new Rep(e, null, false, true, false); } + public static @bind.as("++/") El plusmaxfollow(final El e, final El sep) { return new Rep(e, sep, false, true, true); } + public static @bind.as("+/") El plusfollow(final El e, final El sep) { return new Rep(e, sep, false, true, false); } + public static @bind.as("**") El starmax(final El e) { return new Rep(e, null, true, true, true); } + public static @bind.as("*") El star(final El e) { return new Rep(e, null, true, true, false); } + public static @bind.as("**/") El starmaxfollow(final El e, final El sep) { return new Rep(e, sep, true, true, true); } + public static @bind.as("*/") El starfollow(final El e, final El sep) { return new Rep(e, sep, true, true, false); } + public static @bind.as("?") El question(final El e) { return new Rep(e, null, true, true, false); } - boolean skip = false; - for(String s = br.readLine(); s != null; s = br.readLine()) { - if (s.indexOf("DO NOT EDIT STUFF BELOW: IT IS AUTOMATICALLY GENERATED") != -1 && s.indexOf("\"")==-1) skip = true; - if (s.indexOf("DO NOT EDIT STUFF ABOVE: IT IS AUTOMATICALLY GENERATED") != -1 && s.indexOf("\"")==-1) break; - if (!skip) out.append(s+"\n"); + public static @bind.as("!") El bang(final El e) { return new Drop(e); } + + public static @bind.as("^") El caret(final String s) { + return new Drop(new Constant(CharRange.string(s)) { + public String getOwnerTag() { return s; } + }); } - out.append("\n // DO NOT EDIT STUFF BELOW: IT IS AUTOMATICALLY GENERATED\n"); - Tree ts = new CharParser(MetaGrammar.make()).parse(new FileInputStream(args[0])).expand1(); + public static @bind.as("~") El tilde(final El e) { + return new PostProcess(e) { + public Element postProcess(Element e) { + return infer((Topology)Atom.toAtom(e).complement()); + } }; } - //Forest fs = new CharParser(make()).parse(new FileInputStream(args[0])); - //System.out.println(fs.expand1()); + public static @bind.as("^^") void doublecaret(final El e) { throw new Error("not implemented"); } - //GraphViz gv = new GraphViz(); - //fs.toGraphViz(gv); - //FileOutputStream fox = new FileOutputStream("out.dot"); - //gv.dump(fox); - //fox.close(); - - ts.toJava(out); - out.append("\n // DO NOT EDIT STUFF ABOVE: IT IS AUTOMATICALLY GENERATED\n"); + //public static @bind.as("(") El subexpression(Seq[][] rhs) { return new NonTerminal(rhs); } - for(String s = br.readLine(); s != null; s = br.readLine()) out.append(s+"\n"); - br.close(); + public static @bind.as("Word") String word(String s) { return s; } + public static @bind.as("Quoted") String quoted(String s) { return s; } + public static @bind.as("escaped") String c(char c) { return c+""; } + public static @bind.as("\"\"") String emptystring() { return ""; } + public static @bind.as("\n") String retur() { return "\n"; } + public static @bind.as("\r") String lf() { return "\r"; } - OutputStream os = new FileOutputStream(fileName); - PrintWriter p = new PrintWriter(new OutputStreamWriter(os)); - p.println(out.toString()); - p.flush(); - os.close(); } + public static class Context { + HashMap map = new HashMap(); + private MG.Grammar grammar; + public String cnt = null; + private ReflectiveMeta rm; + public Context(MG.Grammar g, ReflectiveMeta rm) { + this.grammar = g; + this.rm = rm; + } + public Union build() { + Union ret = null; + for(MG.NonTerminal nt : grammar.nonterminals) { + Union u = get(nt.name); + if ("s".equals(nt.name)) + ret = u; + } + return ret; + } + public Context(Tree t, ReflectiveMeta rm) { + this.rm = rm; + Tree.TreeFunctor red = (Tree.TreeFunctor)t.head(); + this.grammar = (MG.Grammar)red.invoke(t.children()); + } + public Union peek(String name) { return map.get(name); } + public void put(String name, Union u) { map.put(name, u); } + public Union get(String name) { + Union ret = map.get(name); + if (ret != null) return ret; + ret = new Union(name); + map.put(name, ret); + MG.NonTerminal nt = grammar.get(name); + if (nt==null) { + System.err.println("*** warning could not find " + name); + } else { + String old = cnt; + cnt = name; + nt.build(this, ret); + cnt = old; + } + return ret; + } + } + /*private*/ static Atom infer(Element e) { return infer((Topology)Atom.toAtom(e)); } + /*private*/ static Atom infer(Topology t) { return new CharRange(new CharTopology(t)); } }