public Object walk(Tree t) {
String head = (String)t.head();
- while(head.indexOf('.') != -1) head = head.substring(head.indexOf('.')+1);
+ while(head.indexOf('.') > 0)
+ head = head.substring(head.indexOf('.')+1);
if (head==null) throw new RuntimeException("head is null: " + t);
if (head.equals("|")) return walkChildren(t);
if (head.equals("RHS")) return walkChildren(t);
if (head.equals("{")) return new XTree((Seq)walk(t.child(0)));
if (head.equals("::")) return tag((String)walk(t.child(0)), (Seq)walk(t.child(1)));
if (head.equals("++")) return plusmax((ElementNode)walk(t.child(0)));
+ if (head.equals("...")) return star(new TildeNode(new AtomNode()));
if (head.equals("+")) return plus((ElementNode)walk(t.child(0)));
if (head.equals("++/")) return plusmaxfollow((ElementNode)walk(t.child(0)), (ElementNode)walk(t.child(1)));
if (head.equals("+/")) return plusfollow((ElementNode)walk(t.child(0)), (ElementNode)walk(t.child(1)));
if (head.equals("?")) return question((ElementNode)walk(t.child(0)));
if (head.equals("!")) return new DropNode((ElementNode)walk(t.child(0)));
if (head.equals("^")) return new LiteralNode((String)walk(t.child(0)), true);
+ if (head.equals("`")) {
+ ElementNode ret = (ElementNode)walk(t.child(0));
+ ret.lifted = true;
+ return ret;
+ }
if (head.equals("Quoted")) return stringifyChildren(t);
if (head.equals("Literal")) return new LiteralNode((String)walk(t.child(0)));
if (head.equals("->")) return arrow((Seq)walk(t.child(0)), (ElementNode)walk(t.child(1)));
if (head.equals("\\{")) return new DropNode(new AtomNode(new AtomNodeRange(CharAtom.left, CharAtom.left)));
if (head.equals("\\}")) return new DropNode(new AtomNode(new AtomNodeRange(CharAtom.right, CharAtom.right)));
if (head.equals("~")) return new TildeNode((ElementNode)walk(t.child(0)));
+ if (head.equals("~~")) {
+ Seq seq = new Seq(star(new TildeNode(new AtomNode())));
+ return seq.andnot((Seq)walk(t.child(0)));
+ }
if (head.equals("Range") && t.size()==1) return new AtomNodeRange(unescape(t).charAt(0));
if (head.equals("Range")) return new AtomNodeRange(unescape(t).charAt(0), unescape(t).charAt(1));
if (head.equals("\"\"")) return "";
File file = new File(f.getAbsolutePath()+File.separatorChar+fileName);
if (!file.exists()) continue;
try {
- String newPrefix = (String)walk(t.child(1));
- if (newPrefix.length() > 0) newPrefix += ".";
+ String newPrefix = t.size()<2 ? "" : ((String)walk(t.child(1))+".");
FileInputStream fis = new FileInputStream(file);
Tree tr = new CharParser(MetaGrammar.newInstance()).parse(fis).expand1();
return (GrammarNode)new GrammarBuilder(includes, newPrefix).walk(tr);
}
throw new RuntimeException("unable to find #include file \""+fileName+"\"");
}
- throw new RuntimeException("unknown head: " + head + "\n"+t);
+ throw new RuntimeException("unknown head: \"" + head + "\" => " + (head.equals("...")));
}
/** A grammar (a set of nonterminals) */
}
if (tag==null && multiNonDrop)
throw new RuntimeException("multiple non-dropped elements in sequence: " + Sequence.create(els, ""));
+ boolean lift = false;
+ if (elements.length > 0 && elements[0].lifted)
+ lift = true;
if (!multiNonDrop) {
if (idx == -1)
ret = tag==null
? Sequence.create(els, illegalTag)
- : Sequence.create(tag, els, drops, false);
+ : Sequence.createLeft(tag, els, drops, lift);
else if (tag==null) ret = Sequence.create(els, idx);
- else ret = Sequence.create(tag, els, drops, false);
+ else ret = Sequence.createLeft(tag, els, drops, lift);
}
if (multiNonDrop)
- ret = Sequence.create(tag, els, drops, false);
+ ret = Sequence.createLeft(tag, els, drops, lift);
if (this.follow != null)
ret = ret.followedBy(this.follow.toAtom(cx));
return ret;
public class ReferenceNode extends ElementNode {
public String nonTerminal;
public ReferenceNode() { }
- public NonTerminalNode resolve(Context cx) { return cx.grammar.get(nonTerminal); }
+ public NonTerminalNode resolve(Context cx) {
+ NonTerminalNode ret = cx.grammar.get(nonTerminal);
+ if (ret==null) throw new RuntimeException("undefined nonterminal: " + nonTerminal);
+ return ret;
+ }
public ReferenceNode(String nonTerminal) { this.nonTerminal = prefix + nonTerminal; }
public Atom toAtom(Context cx) { return cx.grammar.get(nonTerminal).toAtom(cx); }
public boolean drop(Context cx) { return resolve(cx).drop(cx); }
public class AtomNode extends ElementNode {
AtomNodeRange[] ranges;
+ public AtomNode() { this(new AtomNodeRange[0]); }
public AtomNode(AtomNodeRange[] ranges) { this.ranges = ranges; }
public AtomNode(AtomNodeRange range) { this.ranges = new AtomNodeRange[] { range }; }
public Element build(Context cx, NonTerminalNode cnt, boolean dropall) { return toAtom(cx); }
}
public abstract class ElementNode {
+ public boolean lifted = false;
public String getOwnerTag() { return null; }
public boolean drop(Context cx) { return false; }
public Atom toAtom(Context cx) { throw new Error("can't convert a " + this.getClass().getName() + " to an atom: " + this); }
}
- public class XTree extends ElementNode {
- public Seq body;
- public XTree(Seq seq) { this.body = seq; }
- public Element build(Context cx, NonTerminalNode cnt, boolean dropall) {
- Union u = new Union(null, false);
- Sequence s = body.build(cx, u, null, dropall);
- Union u2 = new Union(null, false);
- u2.add(Sequence.create(new Element[] {
- CharAtom.leftBrace,
- cx.get("ws"),
- u,
- cx.get("ws"),
- CharAtom.rightBrace
- }, 2));
- return u2;
- }
- }
}