- public static class MG {
- public static @tag("grammar") class Grammar {
- public @arg("NonTerminal") NonTerminal[] nonterminals;
- public String toString() {
- String ret = "[ ";
- for(NonTerminal nt : nonterminals) ret += nt + ", ";
- return ret + " ]";
- }
- }
- public static @nonterminal class NonTerminal extends El {
- public @arg("Word") String name;
- public @arg("RHS") Seq[][] sequences;
- private static int anon = 0;
- public NonTerminal() { }
- public NonTerminal(Seq[][] sequences) {
- this.name = "anon" + (anon++);
- this.sequences = sequences;
- }
- public Element build(Context cx) {
- Element ret = cx.peek(name);
- if (ret != null) return ret;
- Union u = new Union(name);
- cx.put(name, u);
- HashSet<Sequence> bad = new HashSet<Sequence>();
- for(Seq[] group : sequences) {
- Union u2 = new Union(""+anon++);
- HashSet<Sequence> bad2 = new HashSet<Sequence>();
- for(Seq seq : group) {
- Sequence built = seq.build(cx);
- for(Sequence s : bad)
- built = built.not(s);
- u2.add(built);
- bad2.add(built);
- }
- bad.addAll(bad2);
- u.add(Sequence.singleton(u2));
- }
- return u;
- }
- }
-
- public static @tag void range(char c) { }
- public static class Range {
- public @tag("range") Range(char only) { first = only; last = only; }
- public @tag("-") Range(char first, char last) { this.first = first; this.last = last; }
- public char first;
- public char last;
- }
- 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 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 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 Element build(Context cx) { return e.build(cx); }
- }
- public static /*abstract*/ class Seq {
- HashSet<Seq> and = new HashSet<Seq>();
- HashSet<Seq> not = new HashSet<Seq>();
- El[] elements;
- El follow;
- String tag = null;
- 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 Seq and(Seq s) { and.add(s); return this; }
- public Seq andnot(Seq s) { not.add(s); return this; }
- public Seq separate(El sep) {
- El[] elements = new El[this.elements.length * 2 - 1];
- for(int i=0; i<this.elements.length; i++) {
- elements[i*2] = this.elements[i];
- if (i<this.elements.length-1)
- elements[i*2+1] = new Drop(sep);
- }
- this.elements = elements;
- return this;
- }
- public Sequence build(Context cx) {
- boolean unwrap = false;
- boolean dropAll = false;
- 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<elements.length; i++) {
- labels[i] = elements[i].getLabel();
- drops[i] = elements[i].drop();
- els[i] = elements[i].build(cx);
- if (elements[i].getOwnerTag() != null)
- tag = elements[i].getOwnerTag();
- }
- Sequence ret = null;
- if (dropAll) ret = Sequence.drop(els, false);
- else if (unwrap) ret = Sequence.unwrap(els, repeatTag(), drops);
- else if (tag!=null) {
- //FIXME
- //ret = resolveTag(tag, bc.currentNonTerminal==null ? null : bc.currentNonTerminal.name, els, labels, drops);
- //System.err.println("resolvetag " + tag + " => " + ret);
- ret = Sequence.rewritingSequence(tag, els, labels, drops);
- } else {
- int idx = -1;
- for(int i=0; i<els.length; i++)
- if (!drops[i])
- if (idx==-1) idx = i;
- else throw new Error("multiple non-dropped elements in sequence: " + Sequence.drop(els,false));
- if (idx != -1) ret = Sequence.singleton(els, idx);
- else ret = Sequence.drop(els, false);
- }
- if (this.follow != null)
- ret.follow = MetaGrammar.infer(this.follow.build(cx));
- return ret;
- }
- }
- public static @tag("&") Seq and(Seq s, El[] elements) { return s.and(seq(elements)); }
- public static @tag("&~") Seq andnot(Seq s, El[] elements) { return s.andnot(seq(elements)); }
- public static @tag("->") Seq arrow(Seq s, El e) { return s.follow(e); }
- public static @tag("::") Seq tag(String tagname, Seq s) { return s.tag(tagname); }
- public static @tag("/") Seq slash(Seq s, El e) { return s.separate(e); }
-
- public static @tag("ps") Seq seq(El[] elements) { return new Seq(elements); }
- public static @tag Seq psx(Seq s) { return s; }
- public static @tag(":") El colon(String s, El e) { return new Label(s, e); }
- public static @tag(")") void close(String foo) { throw new Error("not supported"); }
- public static @tag("()") El epsilon() { return new Constant(Union.epsilon); }