abstract sclass CTNode { new LinkedHashSet children; toString { ret shortClassName(this) + ": " + toString2(); } abstract S toString2(); bool add(CTNode n) { ret children.add(n); } } sclass TextNode > CTNode { S text; *() {} *(S *text) {} S toString2() { ret quote(text); } } sclass TokNode > CTNode { L tok; *() {} *(LS *tok) {} S toString2() { ret sfu(tok); } public bool equals(O o) { ret stdEq(this, o, 'tok); } public int hashCode() { ret stdHash(this, 'tok); } } sclass ObjectNode > CTNode { O obj; *() {} *(O *obj) {} S toString2() { ret sfu(obj); } public bool equals(O o) { ret stdEq(this, o, 'obj); } public int hashCode() { ret stdHash(this, 'obj); } } sclass OpNode > CTNode { S op; *() {} *(S *op) {} S toString2() { ret op; } public bool equals(O o) { ret stdEq(this, o, 'op); } public int hashCode() { ret stdHash(this, 'op); } }