- public static class Meta {
- public static class MetaGrammarFile extends HashMap<String,MetaNonterminal> {
- public MetaGrammarFile(Tree<String> tree) {
- if (!tree.head().equals("grammar")) throw new Error();
- for(Tree<String> nt : tree.child(0))
- add(new MetaNonterminal(nt));
- }
- private void add(MetaNonterminal 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(MetaNonterminal mnt : this.values()) ret += mnt + "\n";
+
+ 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<drops.length; i++)
+ if (!drops[i])
+ count++;
+ }
+ }
+
+ public static class Target {
+ public int[] buildSequence(Production p) {
+ Annotation[][] annotations = _bindable.getArgAnnotations();
+ String[] names = _bindable.getArgNames();
+ String name = _bindable.getSimpleName();
+ int len = annotations.length;
+ int ofs = 0;
+ bind.arg[] argtags = new bind.arg[len];
+ for(int i=0; i<names.length; i++)
+ for(Annotation a : annotations[i+ofs])
+ if (a instanceof bind.arg)
+ argtags[i+ofs] = (bind.arg)a;
+ return Target.this.buildSequence(p, names, argtags);
+ }
+ 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 getBind() {
+ return (bind)_bindable.getAnnotation(bind.class); }
+ 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 b = getBind();
+ System.out.println(_bindable.getClass().getSimpleName() + ": " + _bindable.getSimpleName());
+ if (b != null && 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;
+
+ if (b != null && 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<argtags.length; i++)
+ if (argtags[i] != null)
+ argTagged++;
+
+ // FIXME: can be smarter here
+ if (names.length==p.count) {
+ int[] ret = new int[p.count];
+ for(int i=0; i<p.count; i++) ret[i] = i;
+ return ret;
+ } else if (argTagged==p.count) {
+ int[] ret = new int[argtags.length];
+ int j = 0;
+ for(int i=0; i<argtags.length; i++)
+ ret[i] = argtags[i]==null ? -1 : (j++);