X-Git-Url: http://git.megacz.com/?p=sbp.git;a=blobdiff_plain;f=src%2Fedu%2Fberkeley%2Fsbp%2Fmeta%2FMetaGrammarBindings.java;h=0d9052c7efadaed93fb6a0368808727c3aafa098;hp=b70ddb8dc5f462a81d6f548db577abc1a4737c0b;hb=38eb7943a4be918d46cb6517004e57ca91410ce0;hpb=c4b4207ce1be50359c6bd8abe1d657ff8ae8ad6e diff --git a/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java b/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java index b70ddb8..0d9052c 100644 --- a/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java +++ b/src/edu/berkeley/sbp/meta/MetaGrammarBindings.java @@ -10,23 +10,46 @@ 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 { - public @bind.as("Grammar") GrammarNode(NonTerminalNode[] nonterminals) { + public NonTerminalNode[] getNonTerminals() { + return (NonTerminalNode[])values().toArray(new NonTerminalNode[0]); + } + public GrammarNode(NonTerminalNode[] nonterminals) { for(NonTerminalNode nt : nonterminals) { + if (nt==null) continue; if (this.get(nt.name)!=null) throw new RuntimeException("duplicate definition of nonterminal \""+nt.name+"\""); this.put(nt.name, nt); } } + public @bind.as("Grammar") GrammarNode(Object[] nt) { add(nt); } + private void add(Object[] obs) { + for(Object o : obs) { + if (o==null) continue; + else if (o instanceof Object[]) add((Object[])o); + else if (o instanceof NonTerminalNode) { + NonTerminalNode nt = (NonTerminalNode)o; + if (this.get(nt.name)!=null) + throw new RuntimeException("duplicate definition of nonterminal \""+nt.name+"\""); + this.put(nt.name, nt); + } + else if (o instanceof GrammarNode) add(((GrammarNode)o).getNonTerminals()); + } + } public String toString() { String ret = "[ "; 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()) { @@ -62,17 +85,38 @@ public class MetaGrammarBindings { } } + public static @bind.as("#import") GrammarNode poundimport(String fileName, String as) { + if (as==null) as = ""; + else if ("".equals(as)) { } + else as = as +"."; + + try { + 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 class NonTerminalNode extends UnionNode { public boolean rep; public String name = null; public String sep = null; - public @bind.as("NonTerminal") NonTerminalNode(@bind.arg String name, @bind.arg Seq[][] sequences) { this(name, sequences, false); } + 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 NonTerminalNode(String name, Seq[][] sequences, boolean rep) { this(name, sequences, rep, null); } public NonTerminalNode(String name, Seq[][] sequences, boolean rep, String sep) { - this.name = name; + this.name = prefix + name; this.sequences = sequences; this.rep = rep; - this.sep = 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) { @@ -81,7 +125,10 @@ public class MetaGrammarBindings { Union urep = new Union(); 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(); @@ -169,14 +192,14 @@ 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 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; } @@ -201,7 +224,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 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; } @@ -363,10 +395,10 @@ 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(); - this.grammar = (GrammarNode)red.invoke(t.children()); + TreeFunctor red = (TreeFunctor)t.head(); + this.grammar = (GrammarNode)red.invoke(t); } public Union peek(String name) { return map.get(name); } public void put(String name, Union u) { map.put(name, u); } @@ -377,7 +409,7 @@ 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; cnt = name; @@ -389,4 +421,43 @@ public class MetaGrammarBindings { } + public static abstract class ElementNode { + public String getLabel() { return null; } + public String getOwnerTag() { return null; } + public boolean drop() { return false; } + 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 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 abstract static class PostProcess extends ElementNodeWrapper { + ElementNode e; + 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; } + } }