initial add of graph-structured stack. some unit tests. only got singleton merge in there.

This commit is contained in:
Terence Parr 2012-03-17 19:21:52 -07:00
parent ea7037dd2d
commit bdb2aa9d15
4 changed files with 211 additions and 0 deletions

View File

@ -0,0 +1,51 @@
import java.util.Arrays;
public class ArrayNode extends GraphNode {
public final GraphNode[] parents;
public final String[] payloads;
public ArrayNode(SingletonNode a) {
this.parents = new GraphNode[] {a.parent};
this.payloads = new String[] {a.payload};
}
public ArrayNode(GraphNode[] parents, String[] payloads) {
this.parents = parents;
this.payloads = payloads;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
else if ( !(o instanceof ArrayNode) ) {
return false;
}
if ( this.hashCode() != o.hashCode() ) {
return false; // can't be same if hash is different
}
ArrayNode a = (ArrayNode)o;
if ( payloads.length != a.payloads.length ) {
return false;
}
for (int i=0; i<payloads.length; i++) {
if ( !payloads[i].equals(a.payloads[i]) ) return false;
if ( !parents[i].equals(a.parents[i]) ) return false;
}
return true;
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public String toString() {
return Arrays.toString(payloads)+":"+id;
}
}

View File

@ -0,0 +1,58 @@
public abstract class GraphNode {
public static final SingletonNode EMPTY = new SingletonNode(null,"$");
public static int globalNodeCount = 0;
public final int id;
public GraphNode() {
id = globalNodeCount++;
}
public static GraphNode merge(GraphNode a, GraphNode b) { // dispatch
if ( a instanceof SingletonNode && b instanceof SingletonNode ) {
return mergeSingletons((SingletonNode) a, (SingletonNode) b);
}
if ( a instanceof SingletonNode ) {
a = new ArrayNode((SingletonNode)a);
}
if ( b instanceof SingletonNode ) {
b = new ArrayNode((SingletonNode)b);
}
return mergeArrays((ArrayNode) a, (ArrayNode) b);
}
public static GraphNode mergeSingletons(SingletonNode a, SingletonNode b) {
if ( a == EMPTY ) return a;
if ( b == EMPTY ) return b;
if ( a.payload.equals(b.payload) ) {
GraphNode parent = merge(a.parent, b.parent);
if ( parent == a.parent ) return a;
if ( parent == b.parent ) return b;
// new joined parent so create new singleton pointing to it
return new SingletonNode(parent, a.payload);
}
else { // a != b payloads differ
// parents differ, join them; nothing to reuse
if ( !a.parent.equals(b.parent) ) {
ArrayNode joined =
new ArrayNode(new GraphNode[]{a.parent, b.parent},
new String[] {a.payload, b.payload});
return joined;
}
// parents are equal, pick left one as parent to reuse
GraphNode parent = a.parent;
ArrayNode joined =
new ArrayNode(new GraphNode[]{parent, parent},
new String[] {a.payload, b.payload});
return joined;
}
}
public static GraphNode mergeArrays(ArrayNode a, ArrayNode b) {
return null;
}
public static String toDOT(GraphNode a) {
return null;
}
}

View File

@ -0,0 +1,36 @@
public class SingletonNode extends GraphNode {
public final GraphNode parent;
public final String payload;
public SingletonNode(GraphNode parent, String payload) {
this.parent = parent;
this.payload = payload;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
else if ( !(o instanceof SingletonNode) ) {
return false;
}
if ( this.hashCode() != o.hashCode() ) {
return false; // can't be same if hash is different
}
SingletonNode s = (SingletonNode)o;
return payload.equals(s.payload) && parent.equals(s.parent);
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public String toString() {
return payload+":"+id;
}
}

View File

@ -0,0 +1,66 @@
import junit.framework.TestCase;
import org.junit.Test;
public class TestGraphNodes extends TestCase {
@Override
protected void setUp() throws Exception {
GraphNode.globalNodeCount = 1;
}
@Test public void testBothEmpty() {
GraphNode a = GraphNode.EMPTY;
GraphNode b = GraphNode.EMPTY;
GraphNode r = GraphNode.merge(a, b);
assertEquals("$:0", r.toString());
}
@Test public void testLeftEmpty() {
GraphNode a = GraphNode.EMPTY;
GraphNode b = createSingleton(GraphNode.EMPTY, "b");
GraphNode r = GraphNode.merge(a, b);
assertEquals("$:0", r.toString());
}
@Test public void testRightEmpty() {
GraphNode a = GraphNode.EMPTY;
GraphNode b = createSingleton(GraphNode.EMPTY, "b");
GraphNode r = GraphNode.merge(a, b);
assertEquals("$:0", r.toString());
}
@Test public void testSameSingleTops() {
GraphNode a1 = createSingleton(GraphNode.EMPTY, "a");
GraphNode a2 = createSingleton(GraphNode.EMPTY, "a");
GraphNode r = GraphNode.merge(a1, a2);
assertEquals("a:1", r.toString());
}
@Test public void testDiffSingleTops() {
GraphNode a1 = createSingleton(GraphNode.EMPTY, "a");
GraphNode a2 = createSingleton(GraphNode.EMPTY, "b");
GraphNode r = GraphNode.merge(a1, a2);
assertEquals("[a, b]:3", r.toString());
}
@Test public void test_ax_ax_id() {
GraphNode x = createSingleton(GraphNode.EMPTY, "x");
GraphNode a1 = createSingleton(x, "a");
GraphNode a2 = createSingleton(x, "a");
GraphNode r = GraphNode.merge(a1, a2);
assertEquals("a:2", r.toString());
}
@Test public void test_ax_ax_eq() {
GraphNode x1 = createSingleton(GraphNode.EMPTY, "x");
GraphNode x2 = createSingleton(GraphNode.EMPTY, "x");
GraphNode a1 = createSingleton(x1, "a");
GraphNode a2 = createSingleton(x2, "a");
GraphNode r = GraphNode.merge(a1, a2);
assertEquals("a:3", r.toString());
}
public SingletonNode createSingleton(GraphNode parent, String payload) {
SingletonNode a = new SingletonNode(parent, payload);
return a;
}
}